Skip to content

Commit

Permalink
[WEB-2213] fix: group by persistence for list view (#5590)
Browse files Browse the repository at this point in the history
* fix kanban view localStorage

* add functionality for list view and add type for kanban function

* add comment in issue-filter-helper store

* improved code quality

* add comment for clarity

* use better variable names

* use useCallback hook and change variable name

* made suggested changes
  • Loading branch information
sharma01ketan authored Oct 3, 2024
1 parent 8291043 commit b7ee7e1
Show file tree
Hide file tree
Showing 17 changed files with 115 additions and 74 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -199,21 +199,24 @@ export const BaseKanBanRoot: React.FC<IBaseKanBanLayout> = observer((props: IBas
});
};

const handleKanbanFilters = (toggle: "group_by" | "sub_group_by", value: string) => {
if (workspaceSlug) {
let kanbanFilters = issuesFilter?.issueFilters?.kanbanFilters?.[toggle] || [];
if (kanbanFilters.includes(value)) {
kanbanFilters = kanbanFilters.filter((_value) => _value != value);
} else {
kanbanFilters.push(value);
const handleCollapsedGroups = useCallback(
(toggle: "group_by" | "sub_group_by", value: string) => {
if (workspaceSlug) {
let collapsedGroups = issuesFilter?.issueFilters?.kanbanFilters?.[toggle] || [];
if (collapsedGroups.includes(value)) {
collapsedGroups = collapsedGroups.filter((_value) => _value != value);
} else {
collapsedGroups.push(value);
}
updateFilters(projectId?.toString() ?? "", EIssueFilterType.KANBAN_FILTERS, {
[toggle]: collapsedGroups,
});
}
updateFilters(projectId?.toString() ?? "", EIssueFilterType.KANBAN_FILTERS, {
[toggle]: kanbanFilters,
});
}
};
},
[workspaceSlug, issuesFilter, projectId, updateFilters]
);

const kanbanFilters = issuesFilter?.issueFilters?.kanbanFilters || { group_by: [], sub_group_by: [] };
const collapsedGroups = issuesFilter?.issueFilters?.kanbanFilters || { group_by: [], sub_group_by: [] };

return (
<IssueLayoutHOC layout={EIssueLayoutTypes.KANBAN}>
Expand Down Expand Up @@ -258,8 +261,8 @@ export const BaseKanBanRoot: React.FC<IBaseKanBanLayout> = observer((props: IBas
orderBy={orderBy}
updateIssue={updateIssue}
quickActions={renderQuickActions}
handleKanbanFilters={handleKanbanFilters}
kanbanFilters={kanbanFilters}
handleCollapsedGroups={handleCollapsedGroups}
collapsedGroups={collapsedGroups}
enableQuickIssueCreate={enableQuickAdd}
showEmptyGroup={userDisplayFilters?.show_empty_groups ?? true}
quickAddCallback={quickAddIssue}
Expand Down
14 changes: 7 additions & 7 deletions web/core/components/issues/issue-layouts/kanban/default.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ export interface IKanBan {
sub_group_index?: number;
updateIssue: ((projectId: string | null, issueId: string, data: Partial<TIssue>) => Promise<void>) | undefined;
quickActions: TRenderQuickActions;
kanbanFilters: TIssueKanbanFilters;
handleKanbanFilters: any;
collapsedGroups: TIssueKanbanFilters;
handleCollapsedGroups: (toggle: "group_by" | "sub_group_by", value: string) => void;
loadMoreIssues: (groupId?: string, subGroupId?: string) => void;
enableQuickIssueCreate?: boolean;
quickAddCallback?: (projectId: string | null | undefined, data: TIssue) => Promise<TIssue | undefined>;
Expand All @@ -71,8 +71,8 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
sub_group_id = "null",
updateIssue,
quickActions,
kanbanFilters,
handleKanbanFilters,
collapsedGroups,
handleCollapsedGroups,
enableQuickIssueCreate,
quickAddCallback,
loadMoreIssues,
Expand Down Expand Up @@ -133,7 +133,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
if ((getGroupIssueCount(_list.id, undefined, false) ?? 0) > 0) groupVisibility.showGroup = true;
else groupVisibility.showGroup = false;
}
if (kanbanFilters?.group_by.includes(_list.id)) groupVisibility.showIssues = false;
if (collapsedGroups?.group_by.includes(_list.id)) groupVisibility.showIssues = false;
return groupVisibility;
}
};
Expand Down Expand Up @@ -176,8 +176,8 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
issuePayload={subList.payload}
disableIssueCreation={disableIssueCreation || isGroupByCreatedBy}
addIssuesToView={addIssuesToView}
kanbanFilters={kanbanFilters}
handleKanbanFilters={handleKanbanFilters}
collapsedGroups={collapsedGroups}
handleCollapsedGroups={handleCollapsedGroups}
/>
</div>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ interface IHeaderGroupByCard {
icon?: React.ReactNode;
title: string;
count: number;
kanbanFilters: TIssueKanbanFilters;
handleKanbanFilters: any;
collapsedGroups: TIssueKanbanFilters;
handleCollapsedGroups: (toggle: "group_by" | "sub_group_by", value: string) => void;
issuePayload: Partial<TIssue>;
disableIssueCreation?: boolean;
addIssuesToView?: (issueIds: string[]) => Promise<TIssue>;
Expand All @@ -38,13 +38,13 @@ export const HeaderGroupByCard: FC<IHeaderGroupByCard> = observer((props) => {
icon,
title,
count,
kanbanFilters,
handleKanbanFilters,
collapsedGroups,
handleCollapsedGroups,
issuePayload,
disableIssueCreation,
addIssuesToView,
} = props;
const verticalAlignPosition = sub_group_by ? false : kanbanFilters?.group_by.includes(column_id);
const verticalAlignPosition = sub_group_by ? false : collapsedGroups?.group_by.includes(column_id);
// states
const [isOpen, setIsOpen] = React.useState(false);
const [openExistingIssueListModal, setOpenExistingIssueListModal] = React.useState(false);
Expand Down Expand Up @@ -133,7 +133,7 @@ export const HeaderGroupByCard: FC<IHeaderGroupByCard> = observer((props) => {
{sub_group_by === null && (
<div
className="flex h-[20px] w-[20px] flex-shrink-0 cursor-pointer items-center justify-center overflow-hidden rounded-sm transition-all hover:bg-custom-background-80"
onClick={() => handleKanbanFilters("group_by", column_id)}
onClick={() => handleCollapsedGroups("group_by", column_id)}
>
{verticalAlignPosition ? (
<Maximize2 width={14} strokeWidth={2} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,19 @@ interface IHeaderSubGroupByCard {
title: string;
count: number;
column_id: string;
kanbanFilters: TIssueKanbanFilters;
handleKanbanFilters: (toggle: "group_by" | "sub_group_by", value: string) => void;
collapsedGroups: TIssueKanbanFilters;
handleCollapsedGroups: (toggle: "group_by" | "sub_group_by", value: string) => void;
}

export const HeaderSubGroupByCard: FC<IHeaderSubGroupByCard> = observer((props) => {
const { icon, title, count, column_id, kanbanFilters, handleKanbanFilters } = props;
const { icon, title, count, column_id, collapsedGroups, handleCollapsedGroups } = props;
return (
<div
className={`relative flex w-full flex-shrink-0 flex-row items-center gap-1 rounded-sm py-1.5 cursor-pointer`}
onClick={() => handleKanbanFilters("sub_group_by", column_id)}
onClick={() => handleCollapsedGroups("sub_group_by", column_id)}
>
<div className="flex h-[20px] w-[20px] flex-shrink-0 items-center justify-center overflow-hidden rounded-sm transition-all hover:bg-custom-background-80">
{kanbanFilters?.sub_group_by.includes(column_id) ? (
{collapsedGroups?.sub_group_by.includes(column_id) ? (
<ChevronDown width={14} strokeWidth={2} />
) : (
<ChevronUp width={14} strokeWidth={2} />
Expand Down
44 changes: 22 additions & 22 deletions web/core/components/issues/issue-layouts/kanban/swimlanes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ interface ISubGroupSwimlaneHeader {
sub_group_by: TIssueGroupByOptions | undefined;
group_by: TIssueGroupByOptions | undefined;
list: IGroupByColumn[];
kanbanFilters: TIssueKanbanFilters;
handleKanbanFilters: (toggle: "group_by" | "sub_group_by", value: string) => void;
collapsedGroups: TIssueKanbanFilters;
handleCollapsedGroups: (toggle: "group_by" | "sub_group_by", value: string) => void;
showEmptyGroup: boolean;
}

Expand All @@ -53,7 +53,7 @@ const visibilitySubGroupByGroupCount = (subGroupIssueCount: number, showEmptyGro
};

const SubGroupSwimlaneHeader: React.FC<ISubGroupSwimlaneHeader> = observer(
({ getGroupIssueCount, sub_group_by, group_by, list, kanbanFilters, handleKanbanFilters, showEmptyGroup }) => (
({ getGroupIssueCount, sub_group_by, group_by, list, collapsedGroups, handleCollapsedGroups, showEmptyGroup }) => (
<div className="relative flex h-max min-h-full w-full items-center gap-2">
{list &&
list.length > 0 &&
Expand All @@ -73,8 +73,8 @@ const SubGroupSwimlaneHeader: React.FC<ISubGroupSwimlaneHeader> = observer(
icon={_list.icon}
title={_list.name}
count={groupCount}
kanbanFilters={kanbanFilters}
handleKanbanFilters={handleKanbanFilters}
collapsedGroups={collapsedGroups}
handleCollapsedGroups={handleCollapsedGroups}
issuePayload={_list.payload}
/>
</div>
Expand All @@ -96,8 +96,8 @@ interface ISubGroupSwimlane extends ISubGroupSwimlaneHeader {
displayProperties: IIssueDisplayProperties | undefined;
updateIssue: ((projectId: string | null, issueId: string, data: Partial<TIssue>) => Promise<void>) | undefined;
quickActions: TRenderQuickActions;
kanbanFilters: TIssueKanbanFilters;
handleKanbanFilters: (toggle: "group_by" | "sub_group_by", value: string) => void;
collapsedGroups: TIssueKanbanFilters;
handleCollapsedGroups: (toggle: "group_by" | "sub_group_by", value: string) => void;
handleOnDrop: (source: GroupDropLocation, destination: GroupDropLocation) => Promise<void>;
disableIssueCreation?: boolean;
enableQuickIssueCreate: boolean;
Expand All @@ -120,8 +120,8 @@ const SubGroupSwimlane: React.FC<ISubGroupSwimlane> = observer((props) => {
updateIssue,
quickActions,
displayProperties,
kanbanFilters,
handleKanbanFilters,
collapsedGroups,
handleCollapsedGroups,
loadMoreIssues,
showEmptyGroup,
enableQuickIssueCreate,
Expand All @@ -147,7 +147,7 @@ const SubGroupSwimlane: React.FC<ISubGroupSwimlane> = observer((props) => {
if (subGroupCount > 0) subGroupVisibility.showGroup = true;
else subGroupVisibility.showGroup = false;
}
if (kanbanFilters?.sub_group_by.includes(_list.id)) subGroupVisibility.showIssues = false;
if (collapsedGroups?.sub_group_by.includes(_list.id)) subGroupVisibility.showIssues = false;
return subGroupVisibility;
};

Expand All @@ -168,8 +168,8 @@ const SubGroupSwimlane: React.FC<ISubGroupSwimlane> = observer((props) => {
icon={_list.icon}
title={_list.name || ""}
count={issueCount}
kanbanFilters={kanbanFilters}
handleKanbanFilters={handleKanbanFilters}
collapsedGroups={collapsedGroups}
handleCollapsedGroups={handleCollapsedGroups}
/>
</Row>
</div>
Expand All @@ -187,8 +187,8 @@ const SubGroupSwimlane: React.FC<ISubGroupSwimlane> = observer((props) => {
subGroupIndex={subGroupIndex}
updateIssue={updateIssue}
quickActions={quickActions}
kanbanFilters={kanbanFilters}
handleKanbanFilters={handleKanbanFilters}
collapsedGroups={collapsedGroups}
handleCollapsedGroups={handleCollapsedGroups}
showEmptyGroup={showEmptyGroup}
enableQuickIssueCreate={enableQuickIssueCreate}
disableIssueCreation={disableIssueCreation}
Expand Down Expand Up @@ -224,8 +224,8 @@ export interface IKanBanSwimLanes {
group_by: TIssueGroupByOptions | undefined;
updateIssue: ((projectId: string | null, issueId: string, data: Partial<TIssue>) => Promise<void>) | undefined;
quickActions: TRenderQuickActions;
kanbanFilters: TIssueKanbanFilters;
handleKanbanFilters: (toggle: "group_by" | "sub_group_by", value: string) => void;
collapsedGroups: TIssueKanbanFilters;
handleCollapsedGroups: (toggle: "group_by" | "sub_group_by", value: string) => void;
loadMoreIssues: (groupId?: string, subGroupId?: string) => void;
showEmptyGroup: boolean;
handleOnDrop: (source: GroupDropLocation, destination: GroupDropLocation) => Promise<void>;
Expand All @@ -249,8 +249,8 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
orderBy,
updateIssue,
quickActions,
kanbanFilters,
handleKanbanFilters,
collapsedGroups,
handleCollapsedGroups,
loadMoreIssues,
showEmptyGroup,
handleOnDrop,
Expand Down Expand Up @@ -303,8 +303,8 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
getGroupIssueCount={getGroupIssueCount}
group_by={group_by}
sub_group_by={sub_group_by}
kanbanFilters={kanbanFilters}
handleKanbanFilters={handleKanbanFilters}
collapsedGroups={collapsedGroups}
handleCollapsedGroups={handleCollapsedGroups}
list={groupByList}
showEmptyGroup={showEmptyGroup}
/>
Expand All @@ -322,8 +322,8 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
orderBy={orderBy}
updateIssue={updateIssue}
quickActions={quickActions}
kanbanFilters={kanbanFilters}
handleKanbanFilters={handleKanbanFilters}
collapsedGroups={collapsedGroups}
handleCollapsedGroups={handleCollapsedGroups}
loadMoreIssues={loadMoreIssues}
showEmptyGroup={showEmptyGroup}
handleOnDrop={handleOnDrop}
Expand Down
30 changes: 28 additions & 2 deletions web/core/components/issues/issue-layouts/list/base-list-root.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { FC, useCallback, useEffect } from "react";
import { observer } from "mobx-react";
// types
import { GroupByColumnTypes, TGroupedIssues } from "@plane/types";
import { useParams } from "next/navigation";
import { GroupByColumnTypes, TGroupedIssues, TIssueKanbanFilters } from "@plane/types";
// constants
import { EIssueLayoutTypes, EIssuesStoreType } from "@/constants/issue";
import { EIssueFilterType, EIssueLayoutTypes, EIssuesStoreType } from "@/constants/issue";
// hooks
import { useIssues, useUserPermissions } from "@/hooks/store";
// hooks
Expand Down Expand Up @@ -59,6 +60,10 @@ export const BaseListRoot = observer((props: IBaseListRoot) => {
const group_by = (displayFilters?.group_by || null) as GroupByColumnTypes | null;
const showEmptyGroup = displayFilters?.show_empty_groups ?? false;

const { workspaceSlug, projectId } = useParams();
const {updateFilters} = useIssuesActions(storeType);
const collapsedGroups = issuesFilter?.issueFilters?.kanbanFilters || { group_by: [], sub_group_by: [] } as TIssueKanbanFilters;

useEffect(() => {
fetchIssues("init-loader", { canGroup: true, perPageCount: group_by ? 50 : 100 }, viewId);
}, [fetchIssues, storeType, group_by, viewId]);
Expand Down Expand Up @@ -107,6 +112,25 @@ export const BaseListRoot = observer((props: IBaseListRoot) => {
[fetchNextIssues]
);

// kanbanFilters and EIssueFilterType.KANBAN_FILTERS are used becuase the state is shared between kanban view and list view
const handleCollapsedGroups = useCallback(
(value: string) => {
if (workspaceSlug) {
let collapsedGroups = issuesFilter?.issueFilters?.kanbanFilters?.group_by || [];
if (collapsedGroups.includes(value)) {
collapsedGroups = collapsedGroups.filter((_value) => _value != value);
} else {
collapsedGroups.push(value);
}
updateFilters(projectId?.toString() ?? "", EIssueFilterType.KANBAN_FILTERS,
{ group_by: collapsedGroups } as TIssueKanbanFilters
);
}
},
[workspaceSlug, issuesFilter, projectId, updateFilters]
);


return (
<IssueLayoutHOC layout={EIssueLayoutTypes.LIST}>
<div className={`relative size-full bg-custom-background-90`}>
Expand All @@ -127,6 +151,8 @@ export const BaseListRoot = observer((props: IBaseListRoot) => {
addIssuesToView={addIssuesToView}
isCompletedCycle={isCompletedCycle}
handleOnDrop={handleOnDrop}
handleCollapsedGroups={handleCollapsedGroups}
collapsedGroups={collapsedGroups}
/>
</div>
</IssueLayoutHOC>
Expand Down
7 changes: 7 additions & 0 deletions web/core/components/issues/issue-layouts/list/default.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
TIssueGroupByOptions,
TIssueOrderByOptions,
IGroupByColumn,
TIssueKanbanFilters,
} from "@plane/types";
// components
import { MultipleSelectGroup } from "@/components/core";
Expand Down Expand Up @@ -47,6 +48,8 @@ export interface IList {
addIssuesToView?: (issueIds: string[]) => Promise<TIssue>;
isCompletedCycle?: boolean;
loadMoreIssues: (groupId?: string) => void;
handleCollapsedGroups: (value: string) => void;
collapsedGroups : TIssueKanbanFilters;
}

export const List: React.FC<IList> = observer((props) => {
Expand All @@ -67,6 +70,8 @@ export const List: React.FC<IList> = observer((props) => {
addIssuesToView,
isCompletedCycle = false,
loadMoreIssues,
handleCollapsedGroups,
collapsedGroups
} = props;

const storeType = useIssueStoreType();
Expand Down Expand Up @@ -162,6 +167,8 @@ export const List: React.FC<IList> = observer((props) => {
loadMoreIssues={loadMoreIssues}
containerRef={containerRef}
selectionHelpers={helpers}
handleCollapsedGroups={handleCollapsedGroups}
collapsedGroups={collapsedGroups}
/>
))}
</div>
Expand Down
Loading

0 comments on commit b7ee7e1

Please sign in to comment.