diff --git a/web/components/issues/issue-layouts/kanban/default.tsx b/web/components/issues/issue-layouts/kanban/default.tsx index 3cbab589f..5bb46f143 100644 --- a/web/components/issues/issue-layouts/kanban/default.tsx +++ b/web/components/issues/issue-layouts/kanban/default.tsx @@ -58,6 +58,7 @@ export interface IGroupByKanBan { scrollableContainerRef?: MutableRefObject; isDragStarted?: boolean; showEmptyGroup?: boolean; + subGroupIssueHeaderCount?: (listId: string) => number; } const GroupByKanBan: React.FC = observer((props) => { @@ -83,6 +84,7 @@ const GroupByKanBan: React.FC = observer((props) => { scrollableContainerRef, isDragStarted, showEmptyGroup = true, + subGroupIssueHeaderCount, } = props; const member = useMember(); @@ -97,17 +99,27 @@ const GroupByKanBan: React.FC = observer((props) => { if (!list) return null; - const groupWithIssues = list.filter((_list) => (issueIds as TGroupedIssues)?.[_list.id]?.length > 0); - - const groupList = showEmptyGroup ? list : groupWithIssues; - - const visibilityGroupBy = (_list: IGroupByColumn) => { + const visibilityGroupBy = (_list: IGroupByColumn): { showGroup: boolean; showIssues: boolean } => { if (sub_group_by) { - if (kanbanFilters?.sub_group_by.includes(_list.id)) return true; - return false; + const groupVisibility = { + showGroup: true, + showIssues: true, + }; + if (!showEmptyGroup) { + groupVisibility.showGroup = subGroupIssueHeaderCount ? subGroupIssueHeaderCount(_list.id) > 0 : true; + } + return groupVisibility; } else { - if (kanbanFilters?.group_by.includes(_list.id)) return true; - return false; + const groupVisibility = { + showGroup: true, + showIssues: true, + }; + if (!showEmptyGroup) { + if ((issueIds as TGroupedIssues)?.[_list.id]?.length > 0) groupVisibility.showGroup = true; + else groupVisibility.showGroup = false; + } + if (kanbanFilters?.group_by.includes(_list.id)) groupVisibility.showIssues = false; + return groupVisibility; } }; @@ -115,13 +127,18 @@ const GroupByKanBan: React.FC = observer((props) => { return (
- {groupList && - groupList.length > 0 && - groupList.map((_list: IGroupByColumn) => { + {list && + list.length > 0 && + list.map((_list: IGroupByColumn) => { const groupByVisibilityToggle = visibilityGroupBy(_list); + if (groupByVisibilityToggle.showGroup === false) return <>; return ( -
+
{sub_group_by === null && (
= observer((props) => {
)} - {!groupByVisibilityToggle && ( + {groupByVisibilityToggle.showIssues && ( = observer((props) => { viewId={viewId} disableIssueCreation={disableIssueCreation} canEditProperties={canEditProperties} - groupByVisibilityToggle={groupByVisibilityToggle} scrollableContainerRef={scrollableContainerRef} isDragStarted={isDragStarted} /> @@ -197,6 +213,7 @@ export interface IKanBan { canEditProperties: (projectId: string | undefined) => boolean; scrollableContainerRef?: MutableRefObject; isDragStarted?: boolean; + subGroupIssueHeaderCount?: (listId: string) => number; } export const KanBan: React.FC = observer((props) => { @@ -221,6 +238,7 @@ export const KanBan: React.FC = observer((props) => { scrollableContainerRef, isDragStarted, showEmptyGroup, + subGroupIssueHeaderCount, } = props; const issueKanBanView = useKanbanView(); @@ -248,6 +266,7 @@ export const KanBan: React.FC = observer((props) => { scrollableContainerRef={scrollableContainerRef} isDragStarted={isDragStarted} showEmptyGroup={showEmptyGroup} + subGroupIssueHeaderCount={subGroupIssueHeaderCount} /> ); }); diff --git a/web/components/issues/issue-layouts/kanban/kanban-group.tsx b/web/components/issues/issue-layouts/kanban/kanban-group.tsx index a05fb1791..5a46324bd 100644 --- a/web/components/issues/issue-layouts/kanban/kanban-group.tsx +++ b/web/components/issues/issue-layouts/kanban/kanban-group.tsx @@ -37,7 +37,7 @@ interface IKanbanGroup { viewId?: string; disableIssueCreation?: boolean; canEditProperties: (projectId: string | undefined) => boolean; - groupByVisibilityToggle: boolean; + groupByVisibilityToggle?: boolean; scrollableContainerRef?: MutableRefObject; isDragStarted?: boolean; } diff --git a/web/components/issues/issue-layouts/kanban/swimlanes.tsx b/web/components/issues/issue-layouts/kanban/swimlanes.tsx index d60e3b618..11f5304b9 100644 --- a/web/components/issues/issue-layouts/kanban/swimlanes.tsx +++ b/web/components/issues/issue-layouts/kanban/swimlanes.tsx @@ -29,6 +29,7 @@ interface ISubGroupSwimlaneHeader { list: IGroupByColumn[]; kanbanFilters: TIssueKanbanFilters; handleKanbanFilters: (toggle: "group_by" | "sub_group_by", value: string) => void; + showEmptyGroup: boolean; } const getSubGroupHeaderIssuesCount = (issueIds: TSubGroupedIssues, groupById: string) => { @@ -39,6 +40,22 @@ const getSubGroupHeaderIssuesCount = (issueIds: TSubGroupedIssues, groupById: st return headerCount; }; +const visibilitySubGroupByGroupCount = ( + issueIds: TSubGroupedIssues, + _list: IGroupByColumn, + showEmptyGroup: boolean +): boolean => { + let subGroupHeaderVisibility = true; + + if (showEmptyGroup) subGroupHeaderVisibility = true; + else { + if (getSubGroupHeaderIssuesCount(issueIds, _list.id) > 0) subGroupHeaderVisibility = true; + else subGroupHeaderVisibility = false; + } + + return subGroupHeaderVisibility; +}; + const SubGroupSwimlaneHeader: React.FC = ({ issueIds, sub_group_by, @@ -46,25 +63,36 @@ const SubGroupSwimlaneHeader: React.FC = ({ list, kanbanFilters, handleKanbanFilters, + showEmptyGroup, }) => (
{list && list.length > 0 && - list.map((_list: IGroupByColumn) => ( -
- -
- ))} + list.map((_list: IGroupByColumn) => { + const subGroupByVisibilityToggle = visibilitySubGroupByGroupCount( + issueIds as TSubGroupedIssues, + _list, + showEmptyGroup + ); + + if (subGroupByVisibilityToggle === false) return <>; + + return ( +
+ +
+ ); + })}
); @@ -124,52 +152,74 @@ const SubGroupSwimlane: React.FC = observer((props) => { return issueCount; }; + const visibilitySubGroupBy = (_list: IGroupByColumn): { showGroup: boolean; showIssues: boolean } => { + const subGroupVisibility = { + showGroup: true, + showIssues: true, + }; + if (showEmptyGroup) subGroupVisibility.showGroup = true; + else { + if (calculateIssueCount(_list.id) > 0) subGroupVisibility.showGroup = true; + else subGroupVisibility.showGroup = false; + } + if (kanbanFilters?.sub_group_by.includes(_list.id)) subGroupVisibility.showIssues = false; + return subGroupVisibility; + }; + return (
{list && list.length > 0 && - list.map((_list: any) => ( -
-
-
- -
-
-
+ list.map((_list: any) => { + const subGroupByVisibilityToggle = visibilitySubGroupBy(_list); + if (subGroupByVisibilityToggle.showGroup === false) return <>; - {!kanbanFilters?.sub_group_by.includes(_list.id) && ( -
- + return ( +
+
+
+ +
+
- )} -
- ))} + + {subGroupByVisibilityToggle.showIssues && ( +
+ + getSubGroupHeaderIssuesCount(issueIds as TSubGroupedIssues, groupByListId) + } + /> +
+ )} +
+ ); + })}
); }); @@ -261,6 +311,7 @@ export const KanBanSwimLanes: React.FC = observer((props) => { kanbanFilters={kanbanFilters} handleKanbanFilters={handleKanbanFilters} list={groupByList} + showEmptyGroup={showEmptyGroup} />