/** * Copyright (c) 2023-present Plane Software, Inc. and contributors * SPDX-License-Identifier: AGPL-3.0-only * See the LICENSE file for details. */ import type { MutableRefObject } from "react"; import { forwardRef, useCallback, useRef, useState } from "react"; import { observer } from "mobx-react"; //types import type { TGroupedIssues, IIssueDisplayProperties, TSubGroupedIssues, TIssueGroupByOptions, TPaginationData, TLoader, } from "@plane/types"; import { cn } from "@plane/utils"; // hooks import { useIntersectionObserver } from "@/hooks/use-intersection-observer"; // local imports import { KanbanIssueBlocksList } from "./blocks-list"; interface IKanbanGroup { groupId: string; groupedIssueIds: TGroupedIssues | TSubGroupedIssues; displayProperties: IIssueDisplayProperties | undefined; subGroupBy: TIssueGroupByOptions | undefined; subGroupId: string; loadMoreIssues: (groupId?: string, subGroupId?: string) => void; getGroupIssueCount: ( groupId: string | undefined, subGroupId: string | undefined, isSubGroupCumulative: boolean ) => number | undefined; getPaginationData: (groupId: string | undefined, subGroupId: string | undefined) => TPaginationData | undefined; getIssueLoader: (groupId?: string, subGroupId?: string) => TLoader; scrollableContainerRef?: MutableRefObject; } // Loader components const KanbanIssueBlockLoader = forwardRef(function KanbanIssueBlockLoader( props: Record, ref: React.ForwardedRef ) { return ( ); }); KanbanIssueBlockLoader.displayName = "KanbanIssueBlockLoader"; export const KanbanGroup = observer(function KanbanGroup(props: IKanbanGroup) { const { groupId, subGroupId, subGroupBy, displayProperties, groupedIssueIds, loadMoreIssues, getGroupIssueCount, getPaginationData, getIssueLoader, scrollableContainerRef, } = props; // hooks const [intersectionElement, setIntersectionElement] = useState(null); const columnRef = useRef(null); const containerRef = subGroupBy && scrollableContainerRef ? scrollableContainerRef : columnRef; const loadMoreIssuesInThisGroup = useCallback(() => { loadMoreIssues(groupId, subGroupId === "null" ? undefined : subGroupId); }, [loadMoreIssues, groupId, subGroupId]); const isPaginating = !!getIssueLoader(groupId, subGroupId); useIntersectionObserver( containerRef, isPaginating ? null : intersectionElement, loadMoreIssuesInThisGroup, `0% 100% 100% 100%` ); const isSubGroup = !!subGroupId && subGroupId !== "null"; const issueIds = isSubGroup ? ((groupedIssueIds as TSubGroupedIssues)?.[groupId]?.[subGroupId] ?? []) : ((groupedIssueIds as TGroupedIssues)?.[groupId] ?? []); const groupIssueCount = getGroupIssueCount(groupId, subGroupId, false) ?? 0; const nextPageResults = getPaginationData(groupId, subGroupId)?.nextPageResults; const loadMore = isPaginating ? ( ) : (
{" "} Load More ↓
); const shouldLoadMore = nextPageResults === undefined ? issueIds?.length < groupIssueCount : !!nextPageResults; return (
{shouldLoadMore && (isSubGroup ? ( <>{loadMore} ) : (
{Array.from({ length: 2 }).map((_, index) => ( ))}
))}
); });