import { useState } from "react"; import { useRouter } from "next/router"; // react-beautiful-dnd import StrictModeDroppable from "components/dnd/StrictModeDroppable"; import { Draggable } from "react-beautiful-dnd"; // components import { CreateUpdateDraftIssueModal } from "components/issues"; import { BoardHeader, SingleBoardIssue, BoardInlineCreateIssueForm } from "components/core"; // ui import { CustomMenu } from "components/ui"; // icons import { PlusIcon } from "@heroicons/react/24/outline"; // helpers import { replaceUnderscoreIfSnakeCase } from "helpers/string.helper"; // types import { ICurrentUserResponse, IIssue, IIssueViewProps, IState, UserAuth } from "types"; type Props = { addIssueToGroup: () => void; currentState?: IState | null; disableUserActions: boolean; disableAddIssueOption?: boolean; dragDisabled: boolean; groupTitle: string; handleIssueAction: (issue: IIssue, action: "copy" | "delete" | "edit") => void; handleDraftIssueAction?: (issue: IIssue, action: "edit" | "delete") => void; handleTrashBox: (isDragging: boolean) => void; openIssuesListModal?: (() => void) | null; handleMyIssueOpen?: (issue: IIssue) => void; removeIssue: ((bridgeId: string, issueId: string) => void) | null; user: ICurrentUserResponse | undefined; userAuth: UserAuth; viewProps: IIssueViewProps; }; export const SingleBoard: React.FC = (props) => { const { addIssueToGroup, currentState, groupTitle, disableUserActions, disableAddIssueOption = false, dragDisabled, handleIssueAction, handleDraftIssueAction, handleTrashBox, openIssuesListModal, handleMyIssueOpen, removeIssue, user, userAuth, viewProps, } = props; // collapse/expand const [isCollapsed, setIsCollapsed] = useState(true); const [isInlineCreateIssueFormOpen, setIsInlineCreateIssueFormOpen] = useState(false); const [isCreateDraftIssueModalOpen, setIsCreateDraftIssueModalOpen] = useState(false); const { displayFilters, groupedIssues } = viewProps; const router = useRouter(); const { cycleId, moduleId } = router.query; const isMyIssuesPage = router.pathname.split("/")[3] === "my-issues"; const isProfileIssuesPage = router.pathname.split("/")[2] === "profile"; const isDraftIssuesPage = router.pathname.split("/")[4] === "draft-issues"; const type = cycleId ? "cycle" : moduleId ? "module" : "issue"; // Check if it has at least 4 tickets since it is enough to accommodate the Calendar height const issuesLength = groupedIssues?.[groupTitle].length; const hasMinimumNumberOfCards = issuesLength ? issuesLength >= 4 : false; const isNotAllowed = userAuth.isGuest || userAuth.isViewer || disableUserActions; const scrollToBottom = () => { const boardListElement = document.getElementById(`board-list-${groupTitle}`); // timeout is needed because the animation // takes time to complete & we can scroll only after that const timeoutId = setTimeout(() => { if (boardListElement) boardListElement.scrollBy({ top: boardListElement.scrollHeight, left: 0, behavior: "smooth", }); clearTimeout(timeoutId); }, 10); }; const onCreateClick = () => { setIsInlineCreateIssueFormOpen(true); scrollToBottom(); }; const handleAddIssueToGroup = () => { if (isDraftIssuesPage) setIsCreateDraftIssueModalOpen(true); else if (isMyIssuesPage || isProfileIssuesPage) addIssueToGroup(); else onCreateClick(); }; return (
setIsCreateDraftIssueModalOpen(false)} prePopulateData={{ ...(cycleId && { cycle: cycleId.toString() }), ...(moduleId && { module: moduleId.toString() }), [displayFilters?.group_by! === "labels" ? "labels_list" : displayFilters?.group_by!]: displayFilters?.group_by === "labels" ? [groupTitle] : groupTitle, }} /> {isCollapsed && ( {(provided, snapshot) => (
{displayFilters?.order_by !== "sort_order" && ( <>
This board is ordered by{" "} {replaceUnderscoreIfSnakeCase( displayFilters?.order_by ? displayFilters?.order_by[0] === "-" ? displayFilters?.order_by.slice(1) : displayFilters?.order_by : "created_at" )}
)}
{groupedIssues?.[groupTitle].map((issue, index) => ( {(provided, snapshot) => ( handleIssueAction(issue, "edit")} makeIssueCopy={() => handleIssueAction(issue, "copy")} handleDeleteIssue={() => handleIssueAction(issue, "delete")} handleDraftIssueEdit={ handleDraftIssueAction ? () => handleDraftIssueAction(issue, "edit") : undefined } handleDraftIssueDelete={() => handleDraftIssueAction ? handleDraftIssueAction(issue, "delete") : undefined } handleTrashBox={handleTrashBox} handleMyIssueOpen={handleMyIssueOpen} removeIssue={() => { if (removeIssue && issue.bridge_id) removeIssue(issue.bridge_id, issue.id); }} disableUserActions={disableUserActions} user={user} userAuth={userAuth} viewProps={viewProps} /> )} ))} <>{provided.placeholder} setIsInlineCreateIssueFormOpen(false)} onSuccess={() => scrollToBottom()} prePopulatedData={{ ...(cycleId && { cycle: cycleId.toString() }), ...(moduleId && { module: moduleId.toString() }), [displayFilters?.group_by! === "labels" ? "labels_list" : displayFilters?.group_by!]: displayFilters?.group_by === "labels" ? [groupTitle] : groupTitle, }} />
{displayFilters?.group_by !== "created_by" && (
{type === "issue" ? !disableAddIssueOption && !isDraftIssuesPage && ( ) : !disableUserActions && !isDraftIssuesPage && ( Add Issue } position="left" noBorder > { if (isDraftIssuesPage) setIsCreateDraftIssueModalOpen(true); else if (isMyIssuesPage || isProfileIssuesPage) addIssueToGroup(); else onCreateClick(); }} > Create new {openIssuesListModal && ( Add an existing issue )} )}
)}
)} )}
); };