[WEB-749] fix: rendering empty states with "showEmptyGroup" filter in issue grouping (#3954)

* fix: Fixed show empty states in groupBy and subGroupBy in kanban

* lint: lint issue resolved
This commit is contained in:
guru_sainath 2024-03-13 16:59:12 +05:30 committed by GitHub
parent 6ec9c64f7c
commit 898cf98be3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 141 additions and 71 deletions

View File

@ -58,6 +58,7 @@ export interface IGroupByKanBan {
scrollableContainerRef?: MutableRefObject<HTMLDivElement | null>; scrollableContainerRef?: MutableRefObject<HTMLDivElement | null>;
isDragStarted?: boolean; isDragStarted?: boolean;
showEmptyGroup?: boolean; showEmptyGroup?: boolean;
subGroupIssueHeaderCount?: (listId: string) => number;
} }
const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => { const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => {
@ -83,6 +84,7 @@ const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => {
scrollableContainerRef, scrollableContainerRef,
isDragStarted, isDragStarted,
showEmptyGroup = true, showEmptyGroup = true,
subGroupIssueHeaderCount,
} = props; } = props;
const member = useMember(); const member = useMember();
@ -97,17 +99,27 @@ const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => {
if (!list) return null; if (!list) return null;
const groupWithIssues = list.filter((_list) => (issueIds as TGroupedIssues)?.[_list.id]?.length > 0); const visibilityGroupBy = (_list: IGroupByColumn): { showGroup: boolean; showIssues: boolean } => {
const groupList = showEmptyGroup ? list : groupWithIssues;
const visibilityGroupBy = (_list: IGroupByColumn) => {
if (sub_group_by) { if (sub_group_by) {
if (kanbanFilters?.sub_group_by.includes(_list.id)) return true; const groupVisibility = {
return false; showGroup: true,
showIssues: true,
};
if (!showEmptyGroup) {
groupVisibility.showGroup = subGroupIssueHeaderCount ? subGroupIssueHeaderCount(_list.id) > 0 : true;
}
return groupVisibility;
} else { } else {
if (kanbanFilters?.group_by.includes(_list.id)) return true; const groupVisibility = {
return false; 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<IGroupByKanBan> = observer((props) => {
return ( return (
<div className={`relative w-full flex gap-2 ${sub_group_by ? "h-full" : "h-full"}`}> <div className={`relative w-full flex gap-2 ${sub_group_by ? "h-full" : "h-full"}`}>
{groupList && {list &&
groupList.length > 0 && list.length > 0 &&
groupList.map((_list: IGroupByColumn) => { list.map((_list: IGroupByColumn) => {
const groupByVisibilityToggle = visibilityGroupBy(_list); const groupByVisibilityToggle = visibilityGroupBy(_list);
if (groupByVisibilityToggle.showGroup === false) return <></>;
return ( return (
<div className={`relative flex flex-shrink-0 flex-col group ${groupByVisibilityToggle ? `` : `w-[350px]`}`}> <div
className={`relative flex flex-shrink-0 flex-col group ${
groupByVisibilityToggle.showIssues ? `w-[350px]` : ``
} `}
>
{sub_group_by === null && ( {sub_group_by === null && (
<div className="flex-shrink-0 sticky top-0 z-[2] w-full bg-custom-background-90 py-1"> <div className="flex-shrink-0 sticky top-0 z-[2] w-full bg-custom-background-90 py-1">
<HeaderGroupByCard <HeaderGroupByCard
@ -141,7 +158,7 @@ const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => {
</div> </div>
)} )}
{!groupByVisibilityToggle && ( {groupByVisibilityToggle.showIssues && (
<KanbanGroup <KanbanGroup
groupId={_list.id} groupId={_list.id}
issuesMap={issuesMap} issuesMap={issuesMap}
@ -159,7 +176,6 @@ const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => {
viewId={viewId} viewId={viewId}
disableIssueCreation={disableIssueCreation} disableIssueCreation={disableIssueCreation}
canEditProperties={canEditProperties} canEditProperties={canEditProperties}
groupByVisibilityToggle={groupByVisibilityToggle}
scrollableContainerRef={scrollableContainerRef} scrollableContainerRef={scrollableContainerRef}
isDragStarted={isDragStarted} isDragStarted={isDragStarted}
/> />
@ -197,6 +213,7 @@ export interface IKanBan {
canEditProperties: (projectId: string | undefined) => boolean; canEditProperties: (projectId: string | undefined) => boolean;
scrollableContainerRef?: MutableRefObject<HTMLDivElement | null>; scrollableContainerRef?: MutableRefObject<HTMLDivElement | null>;
isDragStarted?: boolean; isDragStarted?: boolean;
subGroupIssueHeaderCount?: (listId: string) => number;
} }
export const KanBan: React.FC<IKanBan> = observer((props) => { export const KanBan: React.FC<IKanBan> = observer((props) => {
@ -221,6 +238,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
scrollableContainerRef, scrollableContainerRef,
isDragStarted, isDragStarted,
showEmptyGroup, showEmptyGroup,
subGroupIssueHeaderCount,
} = props; } = props;
const issueKanBanView = useKanbanView(); const issueKanBanView = useKanbanView();
@ -248,6 +266,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
scrollableContainerRef={scrollableContainerRef} scrollableContainerRef={scrollableContainerRef}
isDragStarted={isDragStarted} isDragStarted={isDragStarted}
showEmptyGroup={showEmptyGroup} showEmptyGroup={showEmptyGroup}
subGroupIssueHeaderCount={subGroupIssueHeaderCount}
/> />
); );
}); });

View File

@ -37,7 +37,7 @@ interface IKanbanGroup {
viewId?: string; viewId?: string;
disableIssueCreation?: boolean; disableIssueCreation?: boolean;
canEditProperties: (projectId: string | undefined) => boolean; canEditProperties: (projectId: string | undefined) => boolean;
groupByVisibilityToggle: boolean; groupByVisibilityToggle?: boolean;
scrollableContainerRef?: MutableRefObject<HTMLDivElement | null>; scrollableContainerRef?: MutableRefObject<HTMLDivElement | null>;
isDragStarted?: boolean; isDragStarted?: boolean;
} }

View File

@ -29,6 +29,7 @@ interface ISubGroupSwimlaneHeader {
list: IGroupByColumn[]; list: IGroupByColumn[];
kanbanFilters: TIssueKanbanFilters; kanbanFilters: TIssueKanbanFilters;
handleKanbanFilters: (toggle: "group_by" | "sub_group_by", value: string) => void; handleKanbanFilters: (toggle: "group_by" | "sub_group_by", value: string) => void;
showEmptyGroup: boolean;
} }
const getSubGroupHeaderIssuesCount = (issueIds: TSubGroupedIssues, groupById: string) => { const getSubGroupHeaderIssuesCount = (issueIds: TSubGroupedIssues, groupById: string) => {
@ -39,6 +40,22 @@ const getSubGroupHeaderIssuesCount = (issueIds: TSubGroupedIssues, groupById: st
return headerCount; 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<ISubGroupSwimlaneHeader> = ({ const SubGroupSwimlaneHeader: React.FC<ISubGroupSwimlaneHeader> = ({
issueIds, issueIds,
sub_group_by, sub_group_by,
@ -46,25 +63,36 @@ const SubGroupSwimlaneHeader: React.FC<ISubGroupSwimlaneHeader> = ({
list, list,
kanbanFilters, kanbanFilters,
handleKanbanFilters, handleKanbanFilters,
showEmptyGroup,
}) => ( }) => (
<div className="relative flex gap-2 h-max min-h-full w-full items-center"> <div className="relative flex gap-2 h-max min-h-full w-full items-center">
{list && {list &&
list.length > 0 && list.length > 0 &&
list.map((_list: IGroupByColumn) => ( list.map((_list: IGroupByColumn) => {
<div key={`${sub_group_by}_${_list.id}`} className="flex w-[350px] flex-shrink-0 flex-col"> const subGroupByVisibilityToggle = visibilitySubGroupByGroupCount(
<HeaderGroupByCard issueIds as TSubGroupedIssues,
sub_group_by={sub_group_by} _list,
group_by={group_by} showEmptyGroup
column_id={_list.id} );
icon={_list.icon}
title={_list.name} if (subGroupByVisibilityToggle === false) return <></>;
count={getSubGroupHeaderIssuesCount(issueIds as TSubGroupedIssues, _list?.id)}
kanbanFilters={kanbanFilters} return (
handleKanbanFilters={handleKanbanFilters} <div key={`${sub_group_by}_${_list.id}`} className="flex w-[350px] flex-shrink-0 flex-col">
issuePayload={_list.payload} <HeaderGroupByCard
/> sub_group_by={sub_group_by}
</div> group_by={group_by}
))} column_id={_list.id}
icon={_list.icon}
title={_list.name}
count={getSubGroupHeaderIssuesCount(issueIds as TSubGroupedIssues, _list?.id)}
kanbanFilters={kanbanFilters}
handleKanbanFilters={handleKanbanFilters}
issuePayload={_list.payload}
/>
</div>
);
})}
</div> </div>
); );
@ -124,52 +152,74 @@ const SubGroupSwimlane: React.FC<ISubGroupSwimlane> = observer((props) => {
return issueCount; 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 ( return (
<div className="relative h-max min-h-full w-full"> <div className="relative h-max min-h-full w-full">
{list && {list &&
list.length > 0 && list.length > 0 &&
list.map((_list: any) => ( list.map((_list: any) => {
<div className="flex flex-shrink-0 flex-col"> const subGroupByVisibilityToggle = visibilitySubGroupBy(_list);
<div className="sticky top-[50px] z-[1] flex w-full items-center bg-custom-background-90 py-1"> if (subGroupByVisibilityToggle.showGroup === false) return <></>;
<div className="sticky left-0 flex-shrink-0 bg-custom-background-90 pr-2">
<HeaderSubGroupByCard
column_id={_list.id}
icon={_list.Icon}
title={_list.name || ""}
count={calculateIssueCount(_list.id)}
kanbanFilters={kanbanFilters}
handleKanbanFilters={handleKanbanFilters}
/>
</div>
<div className="w-full border-b border-dashed border-custom-border-400" />
</div>
{!kanbanFilters?.sub_group_by.includes(_list.id) && ( return (
<div className="relative"> <div className="flex flex-shrink-0 flex-col">
<KanBan <div className="sticky top-[50px] z-[1] flex w-full items-center bg-custom-background-90 py-1">
issuesMap={issuesMap} <div className="sticky left-0 flex-shrink-0 bg-custom-background-90 pr-2">
issueIds={(issueIds as TSubGroupedIssues)?.[_list.id]} <HeaderSubGroupByCard
displayProperties={displayProperties} column_id={_list.id}
sub_group_by={sub_group_by} icon={_list.Icon}
group_by={group_by} title={_list.name || ""}
sub_group_id={_list.id} count={calculateIssueCount(_list.id)}
handleIssues={handleIssues} kanbanFilters={kanbanFilters}
quickActions={quickActions} handleKanbanFilters={handleKanbanFilters}
kanbanFilters={kanbanFilters} />
handleKanbanFilters={handleKanbanFilters} </div>
showEmptyGroup={showEmptyGroup} <div className="w-full border-b border-dashed border-custom-border-400" />
enableQuickIssueCreate={enableQuickIssueCreate}
canEditProperties={canEditProperties}
addIssuesToView={addIssuesToView}
quickAddCallback={quickAddCallback}
viewId={viewId}
scrollableContainerRef={scrollableContainerRef}
isDragStarted={isDragStarted}
/>
</div> </div>
)}
</div> {subGroupByVisibilityToggle.showIssues && (
))} <div className="relative">
<KanBan
issuesMap={issuesMap}
issueIds={(issueIds as TSubGroupedIssues)?.[_list.id]}
displayProperties={displayProperties}
sub_group_by={sub_group_by}
group_by={group_by}
sub_group_id={_list.id}
handleIssues={handleIssues}
quickActions={quickActions}
kanbanFilters={kanbanFilters}
handleKanbanFilters={handleKanbanFilters}
showEmptyGroup={showEmptyGroup}
enableQuickIssueCreate={enableQuickIssueCreate}
canEditProperties={canEditProperties}
addIssuesToView={addIssuesToView}
quickAddCallback={quickAddCallback}
viewId={viewId}
scrollableContainerRef={scrollableContainerRef}
isDragStarted={isDragStarted}
subGroupIssueHeaderCount={(groupByListId: string) =>
getSubGroupHeaderIssuesCount(issueIds as TSubGroupedIssues, groupByListId)
}
/>
</div>
)}
</div>
);
})}
</div> </div>
); );
}); });
@ -261,6 +311,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
kanbanFilters={kanbanFilters} kanbanFilters={kanbanFilters}
handleKanbanFilters={handleKanbanFilters} handleKanbanFilters={handleKanbanFilters}
list={groupByList} list={groupByList}
showEmptyGroup={showEmptyGroup}
/> />
</div> </div>