From 85b7f39ed305d6de09d3f6bb4b969ef6a66f9729 Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal Date: Sat, 4 Feb 2023 20:08:13 +0530 Subject: [PATCH] refactor: integrated global kanban view everywhere --- .../components/core/board-view/all-boards.tsx | 306 ++++++++++++++++++ .../core/board-view/board-header.tsx | 24 +- .../core/board-view/single-board.tsx | 51 ++- .../core/board-view/single-issue.tsx | 7 +- apps/app/components/core/index.ts | 4 +- .../core/{view.tsx => issues-filter-view.tsx} | 0 apps/app/components/issues/board-view.tsx | 245 -------------- apps/app/components/issues/index.ts | 1 - apps/app/components/modules/board-view.tsx | 178 ---------- apps/app/components/modules/index.ts | 1 - .../components/project/cycles/board-view.tsx | 177 ---------- apps/app/pages/[workspaceSlug]/index.tsx | 2 +- .../projects/[projectId]/cycles/[cycleId].tsx | 9 +- .../projects/[projectId]/issues/index.tsx | 12 +- .../[projectId]/modules/[moduleId].tsx | 15 +- 15 files changed, 374 insertions(+), 658 deletions(-) create mode 100644 apps/app/components/core/board-view/all-boards.tsx rename apps/app/components/core/{view.tsx => issues-filter-view.tsx} (100%) delete mode 100644 apps/app/components/issues/board-view.tsx delete mode 100644 apps/app/components/modules/board-view.tsx delete mode 100644 apps/app/components/project/cycles/board-view.tsx diff --git a/apps/app/components/core/board-view/all-boards.tsx b/apps/app/components/core/board-view/all-boards.tsx new file mode 100644 index 000000000..f9b1fcfa2 --- /dev/null +++ b/apps/app/components/core/board-view/all-boards.tsx @@ -0,0 +1,306 @@ +import { useCallback, useState } from "react"; + +import { useRouter } from "next/router"; + +import useSWR, { mutate } from "swr"; + +// react-beautiful-dnd +import { DragDropContext, Draggable, DropResult } from "react-beautiful-dnd"; +// services +import issuesService from "services/issues.service"; +import stateService from "services/state.service"; +// hooks +import useIssueView from "hooks/use-issue-view"; +// components +import StrictModeDroppable from "components/dnd/StrictModeDroppable"; +import { CommonSingleBoard } from "components/core/board-view/single-board"; +import { CreateUpdateIssueModal, DeleteIssueModal } from "components/issues"; +// types +import { + CycleIssueResponse, + IIssue, + IssueResponse, + IState, + ModuleIssueResponse, + UserAuth, +} from "types"; +// fetch-keys +import { CYCLE_ISSUES, MODULE_ISSUES, PROJECT_ISSUES_LIST, STATE_LIST } from "constants/fetch-keys"; + +type Props = { + type?: "issue" | "cycle" | "module"; + issues: IIssue[]; + openIssuesListModal?: () => void; + handleDeleteIssue: React.Dispatch>; + userAuth: UserAuth; +}; + +export const AllBoards: React.FC = ({ + type = "issue", + issues, + openIssuesListModal, + handleDeleteIssue, + userAuth, +}) => { + const [createIssueModal, setCreateIssueModal] = useState(false); + const [isIssueDeletionOpen, setIsIssueDeletionOpen] = useState(false); + const [issueDeletionData, setIssueDeletionData] = useState(); + const [preloadedData, setPreloadedData] = useState< + (Partial & { actionType: "createIssue" | "edit" | "delete" }) | undefined + >(undefined); + + const router = useRouter(); + const { workspaceSlug, projectId, cycleId, moduleId } = router.query; + + const { issueView, groupedByIssues, groupByProperty: selectedGroup } = useIssueView(issues); + + const { data: states, mutate: mutateState } = useSWR( + workspaceSlug && projectId ? STATE_LIST(projectId as string) : null, + workspaceSlug + ? () => stateService.getStates(workspaceSlug as string, projectId as string) + : null + ); + + const handleOnDragEnd = useCallback( + (result: DropResult) => { + if (!result.destination || !workspaceSlug || !projectId) return; + + const { source, destination, type } = result; + + if (type === "state") { + const newStates = Array.from(states ?? []); + const [reorderedState] = newStates.splice(source.index, 1); + newStates.splice(destination.index, 0, reorderedState); + const prevSequenceNumber = newStates[destination.index - 1]?.sequence; + const nextSequenceNumber = newStates[destination.index + 1]?.sequence; + + const sequenceNumber = + prevSequenceNumber && nextSequenceNumber + ? (prevSequenceNumber + nextSequenceNumber) / 2 + : nextSequenceNumber + ? nextSequenceNumber - 15000 / 2 + : prevSequenceNumber + ? prevSequenceNumber + 15000 / 2 + : 15000; + + newStates[destination.index].sequence = sequenceNumber; + + mutateState(newStates, false); + + stateService + .patchState( + workspaceSlug as string, + projectId as string, + newStates[destination.index].id, + { + sequence: sequenceNumber, + } + ) + .then((response) => { + console.log(response); + }) + .catch((err) => { + console.error(err); + }); + } else { + const draggedItem = groupedByIssues[source.droppableId][source.index]; + if (source.droppableId !== destination.droppableId) { + const sourceGroup = source.droppableId; // source group id + const destinationGroup = destination.droppableId; // destination group id + + if (!sourceGroup || !destinationGroup) return; + + if (selectedGroup === "priority") { + // update the removed item for mutation + draggedItem.priority = destinationGroup; + + // patch request + issuesService.patchIssue(workspaceSlug as string, projectId as string, draggedItem.id, { + priority: destinationGroup, + }); + } else if (selectedGroup === "state_detail.name") { + const destinationState = states?.find((s) => s.name === destinationGroup); + const destinationStateId = destinationState?.id; + + // update the removed item for mutation + if (!destinationStateId || !destinationState) return; + draggedItem.state = destinationStateId; + draggedItem.state_detail = destinationState; + + mutate( + PROJECT_ISSUES_LIST(workspaceSlug as string, projectId as string), + (prevData) => { + if (!prevData) return prevData; + + const updatedIssues = prevData.results.map((issue) => { + if (issue.id === draggedItem.id) + return { + ...draggedItem, + state_detail: destinationState, + state: destinationStateId, + }; + + return issue; + }); + + return { + ...prevData, + results: updatedIssues, + }; + }, + false + ); + + if (cycleId) + mutate( + CYCLE_ISSUES(cycleId as string), + (prevData) => { + if (!prevData) return prevData; + const updatedIssues = prevData.map((issue) => { + if (issue.issue_detail.id === draggedItem.id) { + return { + ...issue, + issue_detail: { + ...draggedItem, + state_detail: destinationState, + state: destinationStateId, + }, + }; + } + return issue; + }); + return [...updatedIssues]; + }, + false + ); + + if (moduleId) + mutate( + MODULE_ISSUES(moduleId as string), + (prevData) => { + if (!prevData) return prevData; + const updatedIssues = prevData.map((issue) => { + if (issue.issue_detail.id === draggedItem.id) { + return { + ...issue, + issue_detail: { + ...draggedItem, + state_detail: destinationState, + state: destinationStateId, + }, + }; + } + return issue; + }); + return [...updatedIssues]; + }, + false + ); + + // patch request + issuesService + .patchIssue(workspaceSlug as string, projectId as string, draggedItem.id, { + state: destinationStateId, + }) + .then((res) => { + mutate(CYCLE_ISSUES(cycleId as string)); + mutate(MODULE_ISSUES(moduleId as string)); + mutate(PROJECT_ISSUES_LIST(workspaceSlug as string, projectId as string)); + }); + } + } + } + }, + [ + workspaceSlug, + cycleId, + moduleId, + mutateState, + groupedByIssues, + projectId, + selectedGroup, + states, + ] + ); + + if (issueView !== "kanban") return <>; + + return ( + <> + setIsIssueDeletionOpen(false)} + data={issueDeletionData} + /> + setCreateIssueModal(false)} + prePopulateData={{ + ...preloadedData, + }} + /> + {groupedByIssues ? ( +
+ +
+ + {(provided) => ( +
+
+ {Object.keys(groupedByIssues).map((singleGroup, index) => { + const stateId = + selectedGroup === "state_detail.name" + ? states?.find((s) => s.name === singleGroup)?.id ?? null + : null; + + const bgColor = + selectedGroup === "state_detail.name" + ? states?.find((s) => s.name === singleGroup)?.color + : "#000000"; + + return ( + + {(provided, snapshot) => ( + { + setCreateIssueModal(true); + if (selectedGroup) + setPreloadedData({ + state: stateId !== null ? stateId : undefined, + [selectedGroup]: singleGroup, + actionType: "createIssue", + }); + }} + handleDeleteIssue={handleDeleteIssue} + openIssuesListModal={type !== "issue" ? openIssuesListModal : null} + userAuth={userAuth} + /> + )} + + ); + })} +
+ {provided.placeholder} +
+ )} +
+
+
+
+ ) : ( +
Loading...
+ )} + + ); +}; diff --git a/apps/app/components/core/board-view/board-header.tsx b/apps/app/components/core/board-view/board-header.tsx index 3c76b7ee9..9afbe694a 100644 --- a/apps/app/components/core/board-view/board-header.tsx +++ b/apps/app/components/core/board-view/board-header.tsx @@ -14,6 +14,7 @@ import { addSpaceIfCamelCase } from "helpers/string.helper"; // types import { IIssue, NestedKeyOf } from "types"; type Props = { + provided: DraggableProvided; isCollapsed: boolean; setIsCollapsed: React.Dispatch>; groupedByIssues: { @@ -24,7 +25,6 @@ type Props = { createdBy: string | null; bgColor?: string; addIssueToState: () => void; - provided?: DraggableProvided; }; const BoardHeader: React.FC = ({ @@ -44,18 +44,16 @@ const BoardHeader: React.FC = ({ }`} >
- {provided && ( - - )} +
| null; addIssueToState: () => void; handleDeleteIssue?: Dispatch> | undefined; + openIssuesListModal?: (() => void) | null; userAuth: UserAuth; }; export const CommonSingleBoard: React.FC = ({ + type = "issue", provided, snapshot, bgColor, @@ -44,6 +49,7 @@ export const CommonSingleBoard: React.FC = ({ selectedGroup, addIssueToState, handleDeleteIssue, + openIssuesListModal, userAuth, }) => { // collapse/expand @@ -83,6 +89,7 @@ export const CommonSingleBoard: React.FC = ({ >
= ({ isCollapsed={isCollapsed} setIsCollapsed={setIsCollapsed} selectedGroup={selectedGroup} - provided={provided} /> {(provided, snapshot) => ( @@ -99,8 +105,8 @@ export const CommonSingleBoard: React.FC = ({ className={`mt-3 h-full space-y-3 overflow-y-auto px-3 pb-3 ${ snapshot.isDraggingOver ? "bg-indigo-50 bg-opacity-50" : "" } ${!isCollapsed ? "hidden" : "block"}`} - {...provided.droppableProps} ref={provided.innerRef} + {...provided.droppableProps} > {groupedByIssues[groupTitle].map((childIssue, index: number) => { const assignees = [ @@ -135,14 +141,35 @@ export const CommonSingleBoard: React.FC = ({ ); })} {provided.placeholder} - {/* */} + {type === "issue" ? ( + + ) : ( + + + Add issue + + } + className="mt-1" + optionsPosition="left" + noBorder + > + Create new + {openIssuesListModal && ( + + Add an existing issue + + )} + + )}
)} diff --git a/apps/app/components/core/board-view/single-issue.tsx b/apps/app/components/core/board-view/single-issue.tsx index cd84697e9..f9183e502 100644 --- a/apps/app/components/core/board-view/single-issue.tsx +++ b/apps/app/components/core/board-view/single-issue.tsx @@ -8,9 +8,6 @@ import useSWR, { mutate } from "swr"; // react-beautiful-dnd import { DraggableStateSnapshot } from "react-beautiful-dnd"; -// react-datepicker -import DatePicker from "react-datepicker"; -import "react-datepicker/dist/react-datepicker.css"; // headless ui import { Listbox, Transition } from "@headlessui/react"; // constants @@ -51,7 +48,7 @@ type Props = { typeId?: string; issue: IIssue; properties: Properties; - snapshot?: DraggableStateSnapshot; + snapshot: DraggableStateSnapshot; assignees: Partial[] | (Partial | undefined)[]; people: IWorkspaceMember[] | undefined; handleDeleteIssue?: React.Dispatch>; @@ -163,7 +160,7 @@ const SingleBoardIssue: React.FC = ({ return (
diff --git a/apps/app/components/core/index.ts b/apps/app/components/core/index.ts index dc7fced29..7cfd6d6f5 100644 --- a/apps/app/components/core/index.ts +++ b/apps/app/components/core/index.ts @@ -1,5 +1,5 @@ -export * from "./not-authorized-view"; export * from "./bulk-delete-issues-modal"; export * from "./existing-issues-list-modal"; export * from "./image-upload-modal"; -export * from "./view"; +export * from "./issues-filter-view"; +export * from "./not-authorized-view"; diff --git a/apps/app/components/core/view.tsx b/apps/app/components/core/issues-filter-view.tsx similarity index 100% rename from apps/app/components/core/view.tsx rename to apps/app/components/core/issues-filter-view.tsx diff --git a/apps/app/components/issues/board-view.tsx b/apps/app/components/issues/board-view.tsx deleted file mode 100644 index 04d4156a4..000000000 --- a/apps/app/components/issues/board-view.tsx +++ /dev/null @@ -1,245 +0,0 @@ -import React, { useCallback, useState } from "react"; - -import { useRouter } from "next/router"; - -import useSWR, { mutate } from "swr"; - -// react-beautiful-dnd -import { DragDropContext, Draggable, DropResult } from "react-beautiful-dnd"; -// hook -import useIssueView from "hooks/use-issue-view"; -// services -import stateServices from "services/state.service"; -import issuesServices from "services/issues.service"; -// components -import { CommonSingleBoard } from "components/core/board-view/single-board"; -import StrictModeDroppable from "components/dnd/StrictModeDroppable"; -import { CreateUpdateIssueModal, DeleteIssueModal } from "components/issues"; -// ui -import { Spinner } from "components/ui"; -// types -import type { IState, IIssue, IssueResponse, UserAuth } from "types"; -// fetch-keys -import { STATE_LIST, PROJECT_ISSUES_LIST } from "constants/fetch-keys"; - -type Props = { - issues: IIssue[]; - handleDeleteIssue: React.Dispatch>; - userAuth: UserAuth; -}; - -export const IssuesBoardView: React.FC = ({ issues, handleDeleteIssue, userAuth }) => { - const [createIssueModal, setCreateIssueModal] = useState(false); - const [isIssueDeletionOpen, setIsIssueDeletionOpen] = useState(false); - const [issueDeletionData, setIssueDeletionData] = useState(); - const [preloadedData, setPreloadedData] = useState< - (Partial & { actionType: "createIssue" | "edit" | "delete" }) | undefined - >(undefined); - - const router = useRouter(); - const { workspaceSlug, projectId } = router.query; - - const { issueView, groupedByIssues, groupByProperty: selectedGroup } = useIssueView(issues); - - const { data: states, mutate: mutateState } = useSWR( - workspaceSlug && projectId ? STATE_LIST(projectId as string) : null, - workspaceSlug - ? () => stateServices.getStates(workspaceSlug as string, projectId as string) - : null - ); - - const handleOnDragEnd = useCallback( - (result: DropResult) => { - if (!result.destination || !workspaceSlug || !projectId) return; - - const { source, destination, type } = result; - - if (destination.droppableId === "trashBox") { - // setIssueDeletionData(draggedItem); - setIsIssueDeletionOpen(true); - } else { - if (type === "state") { - const newStates = Array.from(states ?? []); - const [reorderedState] = newStates.splice(source.index, 1); - newStates.splice(destination.index, 0, reorderedState); - const prevSequenceNumber = newStates[destination.index - 1]?.sequence; - const nextSequenceNumber = newStates[destination.index + 1]?.sequence; - - const sequenceNumber = - prevSequenceNumber && nextSequenceNumber - ? (prevSequenceNumber + nextSequenceNumber) / 2 - : nextSequenceNumber - ? nextSequenceNumber - 15000 / 2 - : prevSequenceNumber - ? prevSequenceNumber + 15000 / 2 - : 15000; - - newStates[destination.index].sequence = sequenceNumber; - - mutateState(newStates, false); - - stateServices - .patchState( - workspaceSlug as string, - projectId as string, - newStates[destination.index].id, - { - sequence: sequenceNumber, - } - ) - .then((response) => { - console.log(response); - }) - .catch((err) => { - console.error(err); - }); - } else { - const draggedItem = groupedByIssues[source.droppableId][source.index]; - if (source.droppableId !== destination.droppableId) { - const sourceGroup = source.droppableId; // source group id - const destinationGroup = destination.droppableId; // destination group id - - if (!sourceGroup || !destinationGroup) return; - - if (selectedGroup === "priority") { - // update the removed item for mutation - draggedItem.priority = destinationGroup; - - // patch request - issuesServices.patchIssue( - workspaceSlug as string, - projectId as string, - draggedItem.id, - { - priority: destinationGroup, - } - ); - } else if (selectedGroup === "state_detail.name") { - const destinationState = states?.find((s) => s.name === destinationGroup); - const destinationStateId = destinationState?.id; - - // update the removed item for mutation - if (!destinationStateId || !destinationState) return; - draggedItem.state = destinationStateId; - draggedItem.state_detail = destinationState; - - mutate( - PROJECT_ISSUES_LIST(workspaceSlug as string, projectId as string), - (prevData) => { - if (!prevData) return prevData; - - const updatedIssues = prevData.results.map((issue) => { - if (issue.id === draggedItem.id) - return { - ...draggedItem, - state_detail: destinationState, - state: destinationStateId, - }; - - return issue; - }); - - return { - ...prevData, - results: updatedIssues, - }; - }, - false - ); - - // patch request - issuesServices - .patchIssue(workspaceSlug as string, projectId as string, draggedItem.id, { - state: destinationStateId, - }) - .then((res) => { - mutate(PROJECT_ISSUES_LIST(workspaceSlug as string, projectId as string)); - }); - } - } - } - } - }, - [workspaceSlug, mutateState, groupedByIssues, projectId, selectedGroup, states] - ); - - if (issueView !== "kanban") return <>; - - return ( - <> - setIsIssueDeletionOpen(false)} - data={issueDeletionData} - /> - setCreateIssueModal(false)} - prePopulateData={{ - ...preloadedData, - }} - /> - {groupedByIssues ? ( -
- -
- - {(provided) => ( -
-
- {Object.keys(groupedByIssues).map((singleGroup, index) => { - const stateId = - selectedGroup === "state_detail.name" - ? states?.find((s) => s.name === singleGroup)?.id ?? null - : null; - - return ( - - {(provided, snapshot) => ( - s.name === singleGroup)?.color - : "#000000" - } - groupTitle={singleGroup} - groupedByIssues={groupedByIssues} - selectedGroup={selectedGroup} - addIssueToState={() => { - setCreateIssueModal(true); - if (selectedGroup) - setPreloadedData({ - state: stateId !== null ? stateId : undefined, - [selectedGroup]: singleGroup, - actionType: "createIssue", - }); - }} - handleDeleteIssue={handleDeleteIssue} - userAuth={userAuth} - /> - )} - - ); - })} -
- {provided.placeholder} -
- )} -
-
-
-
- ) : ( -
- -
- )} - - ); -}; diff --git a/apps/app/components/issues/index.ts b/apps/app/components/issues/index.ts index 58d2b2fa0..f2c6a9c64 100644 --- a/apps/app/components/issues/index.ts +++ b/apps/app/components/issues/index.ts @@ -1,7 +1,6 @@ export * from "./comment"; export * from "./sidebar-select"; export * from "./activity"; -export * from "./board-view"; export * from "./delete-issue-modal"; export * from "./description-form"; export * from "./form"; diff --git a/apps/app/components/modules/board-view.tsx b/apps/app/components/modules/board-view.tsx deleted file mode 100644 index a85936158..000000000 --- a/apps/app/components/modules/board-view.tsx +++ /dev/null @@ -1,178 +0,0 @@ -import React, { useCallback } from "react"; - -import { useRouter } from "next/router"; - -import useSWR, { mutate } from "swr"; - -// react-beautiful-dnd -import { DragDropContext, DropResult } from "react-beautiful-dnd"; -// services -import stateService from "services/state.service"; -import issuesService from "services/issues.service"; -// hooks -import useIssueView from "hooks/use-issue-view"; -// components -import { CommonSingleBoard } from "components/core/board-view/single-board"; -// ui -import { Spinner } from "components/ui"; -// types -import { IIssue, ModuleIssueResponse, UserAuth } from "types"; -// constants -import { STATE_LIST, MODULE_ISSUES } from "constants/fetch-keys"; - -type Props = { - issues: IIssue[]; - openCreateIssueModal: (issue?: IIssue, actionType?: "create" | "edit" | "delete") => void; - openIssuesListModal: () => void; - handleDeleteIssue: React.Dispatch>; - setPreloadedData: React.Dispatch< - React.SetStateAction< - | (Partial & { - actionType: "createIssue" | "edit" | "delete"; - }) - | null - > - >; - userAuth: UserAuth; -}; - -export const ModulesBoardView: React.FC = ({ - issues, - openCreateIssueModal, - openIssuesListModal, - handleDeleteIssue, - setPreloadedData, - userAuth, -}) => { - const router = useRouter(); - const { workspaceSlug, projectId, moduleId } = router.query; - - const { issueView, groupedByIssues, groupByProperty: selectedGroup } = useIssueView(issues); - - const { data: states } = useSWR( - workspaceSlug && projectId ? STATE_LIST(projectId as string) : null, - workspaceSlug && projectId - ? () => stateService.getStates(workspaceSlug as string, projectId as string) - : null - ); - - const handleOnDragEnd = useCallback( - (result: DropResult) => { - if (!result.destination) return; - const { source, destination } = result; - - if (source.droppableId !== destination.droppableId) { - const sourceGroup = source.droppableId; // source group id - const destinationGroup = destination.droppableId; // destination group id - if (!sourceGroup || !destinationGroup) return; - - // removed/dragged item - const removedItem = groupedByIssues[source.droppableId][source.index]; - - if (selectedGroup === "priority") { - // update the removed item for mutation - removedItem.priority = destinationGroup; - - // patch request - issuesService.patchIssue(workspaceSlug as string, projectId as string, removedItem.id, { - priority: destinationGroup, - }); - } else if (selectedGroup === "state_detail.name") { - const destinationState = states?.find((s) => s.name === destinationGroup); - const destinationStateId = destinationState?.id; - - // update the removed item for mutation - if (!destinationStateId || !destinationState) return; - removedItem.state = destinationStateId; - removedItem.state_detail = destinationState; - - // patch request - issuesService.patchIssue(workspaceSlug as string, projectId as string, removedItem.id, { - state: destinationStateId, - }); - - if (!moduleId) return; - mutate( - MODULE_ISSUES(moduleId as string), - (prevData) => { - if (!prevData) return prevData; - const updatedIssues = prevData.map((issue) => { - if (issue.issue_detail.id === removedItem.id) { - return { - ...issue, - issue_detail: removedItem, - }; - } - return issue; - }); - return [...updatedIssues]; - }, - false - ); - } - - // remove item from the source group - groupedByIssues[source.droppableId].splice(source.index, 1); - // add item to the destination group - groupedByIssues[destination.droppableId].splice(destination.index, 0, removedItem); - } - }, - [workspaceSlug, groupedByIssues, projectId, selectedGroup, states, moduleId] - ); - - if (issueView !== "kanban") return <>; - - return ( - <> - {groupedByIssues ? ( -
- -
-
-
- {Object.keys(groupedByIssues).map((singleGroup) => { - const stateId = - selectedGroup === "state_detail.name" - ? states?.find((s) => s.name === singleGroup)?.id ?? null - : null; - - return ( - s.name === singleGroup)?.color - : "#000000" - } - groupTitle={singleGroup} - groupedByIssues={groupedByIssues} - selectedGroup={selectedGroup} - addIssueToState={() => { - openCreateIssueModal(); - if (selectedGroup !== null) { - setPreloadedData({ - state: stateId !== null ? stateId : undefined, - [selectedGroup]: singleGroup, - actionType: "createIssue", - }); - } - }} - // openIssuesListModal={openIssuesListModal} - handleDeleteIssue={handleDeleteIssue} - userAuth={userAuth} - /> - ); - })} -
-
-
-
-
- ) : ( -
- -
- )} - - ); -}; diff --git a/apps/app/components/modules/index.ts b/apps/app/components/modules/index.ts index 558a93035..3821cd16b 100644 --- a/apps/app/components/modules/index.ts +++ b/apps/app/components/modules/index.ts @@ -1,6 +1,5 @@ export * from "./select"; export * from "./sidebar-select"; -export * from "./board-view"; export * from "./delete-module-modal"; export * from "./form"; export * from "./list-view"; diff --git a/apps/app/components/project/cycles/board-view.tsx b/apps/app/components/project/cycles/board-view.tsx deleted file mode 100644 index 7dae28ebb..000000000 --- a/apps/app/components/project/cycles/board-view.tsx +++ /dev/null @@ -1,177 +0,0 @@ -import React, { useCallback } from "react"; -// swr -import useSWR, { mutate } from "swr"; -// services -import { useRouter } from "next/router"; -import { DragDropContext, DropResult } from "react-beautiful-dnd"; -import stateService from "services/state.service"; -// hooks -import useIssueView from "hooks/use-issue-view"; -// components -import { CommonSingleBoard } from "components/core/board-view/single-board"; -// ui -import { Spinner } from "components/ui"; -// types -import { CycleIssueResponse, IIssue, UserAuth } from "types"; -import issuesService from "services/issues.service"; -// constants -import { STATE_LIST, CYCLE_ISSUES } from "constants/fetch-keys"; - -type Props = { - issues: IIssue[]; - openCreateIssueModal: (issue?: IIssue, actionType?: "create" | "edit" | "delete") => void; - openIssuesListModal: () => void; - handleDeleteIssue: React.Dispatch>; - setPreloadedData: React.Dispatch< - React.SetStateAction< - | (Partial & { - actionType: "createIssue" | "edit" | "delete"; - }) - | null - > - >; - userAuth: UserAuth; -}; - -const CyclesBoardView: React.FC = ({ - issues, - openCreateIssueModal, - openIssuesListModal, - handleDeleteIssue, - setPreloadedData, - userAuth, -}) => { - const router = useRouter(); - const { workspaceSlug, projectId, cycleId } = router.query; - - const { issueView, groupedByIssues, groupByProperty: selectedGroup } = useIssueView(issues); - - const { data: states } = useSWR( - workspaceSlug && projectId ? STATE_LIST(projectId as string) : null, - workspaceSlug && projectId - ? () => stateService.getStates(workspaceSlug as string, projectId as string) - : null - ); - - const handleOnDragEnd = useCallback( - (result: DropResult) => { - if (!result.destination) return; - const { source, destination } = result; - - if (source.droppableId !== destination.droppableId) { - const sourceGroup = source.droppableId; // source group id - const destinationGroup = destination.droppableId; // destination group id - if (!sourceGroup || !destinationGroup) return; - - // removed/dragged item - const removedItem = groupedByIssues[source.droppableId][source.index]; - - if (selectedGroup === "priority") { - // update the removed item for mutation - removedItem.priority = destinationGroup; - - // patch request - issuesService.patchIssue(workspaceSlug as string, projectId as string, removedItem.id, { - priority: destinationGroup, - }); - } else if (selectedGroup === "state_detail.name") { - const destinationState = states?.find((s) => s.name === destinationGroup); - const destinationStateId = destinationState?.id; - - // update the removed item for mutation - if (!destinationStateId || !destinationState) return; - removedItem.state = destinationStateId; - removedItem.state_detail = destinationState; - - // patch request - issuesService.patchIssue(workspaceSlug as string, projectId as string, removedItem.id, { - state: destinationStateId, - }); - - if (!cycleId) return; - mutate( - CYCLE_ISSUES(cycleId as string), - (prevData) => { - if (!prevData) return prevData; - const updatedIssues = prevData.map((issue) => { - if (issue.issue_detail.id === removedItem.id) { - return { - ...issue, - issue_detail: removedItem, - }; - } - return issue; - }); - return [...updatedIssues]; - }, - false - ); - } - - // remove item from the source group - groupedByIssues[source.droppableId].splice(source.index, 1); - // add item to the destination group - groupedByIssues[destination.droppableId].splice(destination.index, 0, removedItem); - } - }, - [workspaceSlug, groupedByIssues, projectId, selectedGroup, states, cycleId] - ); - - if (issueView !== "kanban") return <>; - - return ( - <> - {groupedByIssues ? ( -
- -
-
-
- {Object.keys(groupedByIssues).map((singleGroup) => { - const stateId = - selectedGroup === "state_detail.name" - ? states?.find((s) => s.name === singleGroup)?.id ?? null - : null; - - return ( - s.name === singleGroup)?.color - : "#000000" - } - groupTitle={singleGroup} - groupedByIssues={groupedByIssues} - selectedGroup={selectedGroup} - addIssueToState={() => { - openCreateIssueModal(); - if (selectedGroup !== null) { - setPreloadedData({ - state: stateId !== null ? stateId : undefined, - [selectedGroup]: singleGroup, - actionType: "createIssue", - }); - } - }} - // openIssuesListModal={openIssuesListModal} - handleDeleteIssue={handleDeleteIssue} - userAuth={userAuth} - /> - ); - })} -
-
-
-
-
- ) : ( -
- -
- )} - - ); -}; - -export default CyclesBoardView; diff --git a/apps/app/pages/[workspaceSlug]/index.tsx b/apps/app/pages/[workspaceSlug]/index.tsx index 83f9ff4dd..ec3a28711 100644 --- a/apps/app/pages/[workspaceSlug]/index.tsx +++ b/apps/app/pages/[workspaceSlug]/index.tsx @@ -191,7 +191,7 @@ const WorkspacePage: NextPage = () => {
{project.icon ? ( - + {String.fromCodePoint(parseInt(project.icon))} ) : ( diff --git a/apps/app/pages/[workspaceSlug]/projects/[projectId]/cycles/[cycleId].tsx b/apps/app/pages/[workspaceSlug]/projects/[projectId]/cycles/[cycleId].tsx index ef359ca6f..87215fade 100644 --- a/apps/app/pages/[workspaceSlug]/projects/[projectId]/cycles/[cycleId].tsx +++ b/apps/app/pages/[workspaceSlug]/projects/[projectId]/cycles/[cycleId].tsx @@ -12,10 +12,10 @@ import AppLayout from "layouts/app-layout"; 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, DeleteIssueModal } from "components/issues"; import { ExistingIssuesListModal, IssuesFilterView } from "components/core"; import CycleDetailSidebar from "components/project/cycles/cycle-detail-sidebar"; +import { AllBoards } from "components/core/board-view/all-boards"; // services import issuesServices from "services/issues.service"; import cycleServices from "services/cycles.service"; @@ -242,12 +242,11 @@ const SingleCycle: React.FC = (props) => { setPreloadedData={setPreloadedData} userAuth={props} /> -
diff --git a/apps/app/pages/[workspaceSlug]/projects/[projectId]/issues/index.tsx b/apps/app/pages/[workspaceSlug]/projects/[projectId]/issues/index.tsx index 7e3126e8a..24b72d708 100644 --- a/apps/app/pages/[workspaceSlug]/projects/[projectId]/issues/index.tsx +++ b/apps/app/pages/[workspaceSlug]/projects/[projectId]/issues/index.tsx @@ -1,6 +1,6 @@ import { useEffect, useState } from "react"; import { useRouter } from "next/router"; -import useSWR, { mutate } from "swr"; +import useSWR from "swr"; import { RectangleStackIcon } from "@heroicons/react/24/outline"; import { PlusIcon } from "@heroicons/react/20/solid"; // lib @@ -13,13 +13,9 @@ import AppLayout from "layouts/app-layout"; // contexts import { IssueViewContextProvider } from "contexts/issue-view.context"; // components -import { - CreateUpdateIssueModal, - DeleteIssueModal, - IssuesBoardView, - IssuesListView, -} from "components/issues"; import { IssuesFilterView } from "components/core"; +import { CreateUpdateIssueModal, DeleteIssueModal, IssuesListView } from "components/issues"; +import { AllBoards } from "components/core/board-view/all-boards"; // ui import { Spinner, EmptySpace, EmptySpaceItem, HeaderButton } from "components/ui"; import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs"; @@ -119,7 +115,7 @@ const ProjectIssues: NextPage = (props) => { handleEditIssue={handleEditIssue} userAuth={props} /> - p.parent === null) ?? []} handleDeleteIssue={setDeleteIssue} 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 e5a6f34ba..b665ef93b 100644 --- a/apps/app/pages/[workspaceSlug]/projects/[projectId]/modules/[moduleId].tsx +++ b/apps/app/pages/[workspaceSlug]/projects/[projectId]/modules/[moduleId].tsx @@ -16,12 +16,8 @@ import { IssueViewContextProvider } from "contexts/issue-view.context"; // components import { ExistingIssuesListModal, IssuesFilterView } from "components/core"; import { CreateUpdateIssueModal, DeleteIssueModal } from "components/issues"; -import { - DeleteModuleModal, - ModuleDetailsSidebar, - ModulesListView, - ModulesBoardView, -} from "components/modules"; +import { AllBoards } from "components/core/board-view/all-boards"; +import { DeleteModuleModal, ModuleDetailsSidebar, ModulesListView } from "components/modules"; // ui import { CustomMenu, EmptySpace, EmptySpaceItem, Spinner } from "components/ui"; import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs"; @@ -266,12 +262,11 @@ const SingleModule: React.FC = (props) => { setPreloadedData={setPreloadedData} userAuth={props} /> -