/** * 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 { Fragment, forwardRef, useRef, useState } from "react"; import { observer } from "mobx-react"; import { useTranslation } from "@plane/i18n"; // plane types import type { IGroupByColumn, TIssueGroupByOptions, IIssueDisplayProperties, TPaginationData, TLoader, } from "@plane/types"; // plane utils import { cn } from "@plane/utils"; // hooks import { useIntersectionObserver } from "@/hooks/use-intersection-observer"; // import { IssueBlocksList } from "./blocks-list"; import { HeaderGroupByCard } from "./headers/group-by-card"; interface Props { groupIssueIds: string[] | undefined; group: IGroupByColumn; groupBy: TIssueGroupByOptions | undefined; displayProperties: IIssueDisplayProperties | undefined; containerRef: MutableRefObject; showEmptyGroup?: boolean; loadMoreIssues: (groupId?: 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; } // List loader component const ListLoaderItemRow = forwardRef(function ListLoaderItemRow( props: Record, ref: React.ForwardedRef ) { return (
{[...Array(6)].map((_, index) => ( ))}
); }); ListLoaderItemRow.displayName = "ListLoaderItemRow"; export const ListGroup = observer(function ListGroup(props: Props) { const { groupIssueIds = [], group, groupBy, displayProperties, containerRef, showEmptyGroup, loadMoreIssues, getGroupIssueCount, getPaginationData, getIssueLoader, } = props; const [isExpanded, setIsExpanded] = useState(true); const groupRef = useRef(null); // hooks const { t } = useTranslation(); const [intersectionElement, setIntersectionElement] = useState(null); const groupIssueCount = getGroupIssueCount(group.id, undefined, false) ?? 0; const nextPageResults = getPaginationData(group.id, undefined)?.nextPageResults; const isPaginating = !!getIssueLoader(group.id); useIntersectionObserver(containerRef, isPaginating ? null : intersectionElement, loadMoreIssues, `100% 0% 100% 0%`); const shouldLoadMore = nextPageResults === undefined && groupIssueCount !== undefined && groupIssueIds ? groupIssueIds.length < groupIssueCount : !!nextPageResults; const loadMore = isPaginating ? ( ) : (
loadMoreIssues(group.id)} role="button" > {t("common.load_more")} ↓
); const validateEmptyIssueGroups = (issueCount: number = 0) => { if (!showEmptyGroup && issueCount <= 0) return false; return true; }; const toggleListGroup = () => { setIsExpanded((prevState) => !prevState); }; const shouldExpand = (!!groupIssueCount && isExpanded) || !groupBy; return validateEmptyIssueGroups(groupIssueCount) ? (
{shouldExpand && (
{groupIssueIds && ( )} {shouldLoadMore && (groupBy ? <>{loadMore} : )}
)}
) : null; });