/** * 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 { useState } from "react"; import { observer } from "mobx-react"; // types import type { GroupByColumnTypes, IGroupByColumn, TGroupedIssues, IIssueDisplayProperties, TSubGroupedIssues, TIssueGroupByOptions, TIssueOrderByOptions, TPaginationData, TLoader, } from "@plane/types"; // hooks import { useCycle } from "@/hooks/store/use-cycle"; import { useLabel } from "@/hooks/store/use-label"; import { useMember } from "@/hooks/store/use-member"; import { useModule } from "@/hooks/store/use-module"; import { useStates } from "@/hooks/store/use-state"; // import { getGroupByColumns } from "../utils"; import { KanBan } from "./default"; import { HeaderGroupByCard } from "./headers/group-by-card"; import { HeaderSubGroupByCard } from "./headers/sub-group-by-card"; export interface IKanBanSwimLanes { groupedIssueIds: TGroupedIssues | TSubGroupedIssues; displayProperties: IIssueDisplayProperties | undefined; subGroupBy: TIssueGroupByOptions | undefined; groupBy: TIssueGroupByOptions | undefined; 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; showEmptyGroup: boolean; scrollableContainerRef?: MutableRefObject; orderBy: TIssueOrderByOptions | undefined; } export const KanBanSwimLanes = observer(function KanBanSwimLanes(props: IKanBanSwimLanes) { const { groupedIssueIds, displayProperties, subGroupBy, groupBy, orderBy, loadMoreIssues, getGroupIssueCount, getPaginationData, getIssueLoader, showEmptyGroup, scrollableContainerRef, } = props; const member = useMember(); const label = useLabel(); const cycle = useCycle(); const modules = useModule(); const state = useStates(); const groupByList = getGroupByColumns(groupBy as GroupByColumnTypes, cycle, modules, label, state, member); const subGroupByList = getGroupByColumns(subGroupBy as GroupByColumnTypes, cycle, modules, label, state, member); if (!groupByList || !subGroupByList) return null; return (
{subGroupBy && ( )}
); }); interface ISubGroupSwimlaneHeader { subGroupBy: TIssueGroupByOptions | undefined; groupBy: TIssueGroupByOptions | undefined; groupList: IGroupByColumn[]; showEmptyGroup: boolean; getGroupIssueCount: ( groupId: string | undefined, subGroupId: string | undefined, isSubGroupCumulative: boolean ) => number | undefined; } const visibilitySubGroupByGroupCount = (subGroupIssueCount: number, showEmptyGroup: boolean): boolean => { let subGroupHeaderVisibility = true; if (showEmptyGroup) subGroupHeaderVisibility = true; else { if (subGroupIssueCount > 0) subGroupHeaderVisibility = true; else subGroupHeaderVisibility = false; } return subGroupHeaderVisibility; }; const SubGroupSwimlaneHeader = observer(function SubGroupSwimlaneHeader({ subGroupBy, groupBy, groupList, showEmptyGroup, getGroupIssueCount, }: ISubGroupSwimlaneHeader) { return (
{groupList && groupList.length > 0 && groupList.map((group: IGroupByColumn) => { const groupCount = getGroupIssueCount(group.id, undefined, false) ?? 0; const subGroupByVisibilityToggle = visibilitySubGroupByGroupCount(groupCount, showEmptyGroup); if (subGroupByVisibilityToggle === false) return <>; return (
); })}
); }); interface ISubGroupSwimlane extends ISubGroupSwimlaneHeader { groupedIssueIds: TGroupedIssues | TSubGroupedIssues; showEmptyGroup: boolean; displayProperties: IIssueDisplayProperties | undefined; orderBy: TIssueOrderByOptions | undefined; 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; loadMoreIssues: (groupId?: string, subGroupId?: string) => void; } const SubGroupSwimlane = observer(function SubGroupSwimlane(props: ISubGroupSwimlane) { const { groupedIssueIds, subGroupBy, groupBy, groupList, displayProperties, loadMoreIssues, getGroupIssueCount, getPaginationData, getIssueLoader, showEmptyGroup, scrollableContainerRef, } = props; return (
{groupList && groupList.length > 0 && groupList.map((group: IGroupByColumn) => ( ))}
); }); interface ISubGroup { groupedIssueIds: TGroupedIssues | TSubGroupedIssues; showEmptyGroup: boolean; displayProperties: IIssueDisplayProperties | undefined; groupBy: TIssueGroupByOptions | undefined; subGroupBy: TIssueGroupByOptions | undefined; group: IGroupByColumn; 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; loadMoreIssues: (groupId?: string, subGroupId?: string) => void; } const SubGroup = observer(function SubGroup(props: ISubGroup) { const { groupedIssueIds, subGroupBy, groupBy, group, displayProperties, loadMoreIssues, getGroupIssueCount, getPaginationData, getIssueLoader, showEmptyGroup, scrollableContainerRef, } = props; const [isExpanded, setIsExpanded] = useState(true); const toggleExpanded = () => { setIsExpanded((prevState) => !prevState); }; const visibilitySubGroupBy = ( _list: IGroupByColumn, subGroupCount: number ): { showGroup: boolean; showIssues: boolean } => { const subGroupVisibility = { showGroup: true, showIssues: true, }; if (showEmptyGroup) subGroupVisibility.showGroup = true; else { if (subGroupCount > 0) subGroupVisibility.showGroup = true; else subGroupVisibility.showGroup = false; } return subGroupVisibility; }; const issueCount = getGroupIssueCount(undefined, group.id, true) ?? 0; const subGroupByVisibilityToggle = visibilitySubGroupBy(group, issueCount); if (subGroupByVisibilityToggle.showGroup === false) return <>; return ( <>
{subGroupByVisibilityToggle.showIssues && isExpanded && (
)}
); });