mirror of
https://github.com/makeplane/plane.git
synced 2025-12-25 08:09:33 +01:00
[WEB-2213] fix: group by persistence for list view (#5590)
* 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
This commit is contained in:
@@ -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}>
|
||||
@@ -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}
|
||||
|
||||
@@ -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>;
|
||||
@@ -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,
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
@@ -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>
|
||||
)}
|
||||
|
||||
@@ -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>;
|
||||
@@ -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);
|
||||
@@ -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} />
|
||||
|
||||
@@ -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} />
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 &&
|
||||
@@ -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>
|
||||
@@ -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;
|
||||
@@ -120,8 +120,8 @@ const SubGroupSwimlane: React.FC<ISubGroupSwimlane> = observer((props) => {
|
||||
updateIssue,
|
||||
quickActions,
|
||||
displayProperties,
|
||||
kanbanFilters,
|
||||
handleKanbanFilters,
|
||||
collapsedGroups,
|
||||
handleCollapsedGroups,
|
||||
loadMoreIssues,
|
||||
showEmptyGroup,
|
||||
enableQuickIssueCreate,
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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>
|
||||
@@ -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}
|
||||
@@ -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>;
|
||||
@@ -249,8 +249,8 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
|
||||
orderBy,
|
||||
updateIssue,
|
||||
quickActions,
|
||||
kanbanFilters,
|
||||
handleKanbanFilters,
|
||||
collapsedGroups,
|
||||
handleCollapsedGroups,
|
||||
loadMoreIssues,
|
||||
showEmptyGroup,
|
||||
handleOnDrop,
|
||||
@@ -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}
|
||||
/>
|
||||
@@ -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}
|
||||
|
||||
@@ -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
|
||||
@@ -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]);
|
||||
@@ -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`}>
|
||||
@@ -127,6 +151,8 @@ export const BaseListRoot = observer((props: IBaseListRoot) => {
|
||||
addIssuesToView={addIssuesToView}
|
||||
isCompletedCycle={isCompletedCycle}
|
||||
handleOnDrop={handleOnDrop}
|
||||
handleCollapsedGroups={handleCollapsedGroups}
|
||||
collapsedGroups={collapsedGroups}
|
||||
/>
|
||||
</div>
|
||||
</IssueLayoutHOC>
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
TIssueGroupByOptions,
|
||||
TIssueOrderByOptions,
|
||||
IGroupByColumn,
|
||||
TIssueKanbanFilters,
|
||||
} from "@plane/types";
|
||||
// components
|
||||
import { MultipleSelectGroup } from "@/components/core";
|
||||
@@ -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) => {
|
||||
@@ -67,6 +70,8 @@ export const List: React.FC<IList> = observer((props) => {
|
||||
addIssuesToView,
|
||||
isCompletedCycle = false,
|
||||
loadMoreIssues,
|
||||
handleCollapsedGroups,
|
||||
collapsedGroups
|
||||
} = props;
|
||||
|
||||
const storeType = useIssueStoreType();
|
||||
@@ -162,6 +167,8 @@ export const List: React.FC<IList> = observer((props) => {
|
||||
loadMoreIssues={loadMoreIssues}
|
||||
containerRef={containerRef}
|
||||
selectionHelpers={helpers}
|
||||
handleCollapsedGroups={handleCollapsedGroups}
|
||||
collapsedGroups={collapsedGroups}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -26,10 +26,10 @@ interface IHeaderGroupByCard {
|
||||
count: number;
|
||||
issuePayload: Partial<TIssue>;
|
||||
canEditProperties: (projectId: string | undefined) => boolean;
|
||||
toggleListGroup: () => void;
|
||||
disableIssueCreation?: boolean;
|
||||
addIssuesToView?: (issueIds: string[]) => Promise<TIssue>;
|
||||
selectionHelpers: TSelectionHelper;
|
||||
handleCollapsedGroups: (value: string) => void;
|
||||
}
|
||||
|
||||
export const HeaderGroupByCard = observer((props: IHeaderGroupByCard) => {
|
||||
@@ -43,7 +43,7 @@ export const HeaderGroupByCard = observer((props: IHeaderGroupByCard) => {
|
||||
disableIssueCreation,
|
||||
addIssuesToView,
|
||||
selectionHelpers,
|
||||
toggleListGroup,
|
||||
handleCollapsedGroups
|
||||
} = props;
|
||||
// states
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
@@ -108,7 +108,7 @@ export const HeaderGroupByCard = observer((props: IHeaderGroupByCard) => {
|
||||
|
||||
<div
|
||||
className="relative flex w-full flex-row items-center gap-1 overflow-hidden cursor-pointer"
|
||||
onClick={toggleListGroup}
|
||||
onClick={() => handleCollapsedGroups(groupID)}
|
||||
>
|
||||
<div className="inline-block line-clamp-1 truncate font-medium text-custom-text-100">{title}</div>
|
||||
<div className="pl-2 text-sm font-medium text-custom-text-300">{count || 0}</div>
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
TIssueOrderByOptions,
|
||||
TIssue,
|
||||
IIssueDisplayProperties,
|
||||
TIssueKanbanFilters,
|
||||
} from "@plane/types";
|
||||
import { Row, setToast, TOAST_TYPE } from "@plane/ui";
|
||||
// components
|
||||
@@ -60,6 +61,8 @@ interface Props {
|
||||
showEmptyGroup?: boolean;
|
||||
loadMoreIssues: (groupId?: string) => void;
|
||||
selectionHelpers: TSelectionHelper;
|
||||
handleCollapsedGroups: (value: string) => void;
|
||||
collapsedGroups: TIssueKanbanFilters;
|
||||
}
|
||||
|
||||
export const ListGroup = observer((props: Props) => {
|
||||
@@ -84,11 +87,13 @@ export const ListGroup = observer((props: Props) => {
|
||||
showEmptyGroup,
|
||||
loadMoreIssues,
|
||||
selectionHelpers,
|
||||
handleCollapsedGroups,
|
||||
collapsedGroups,
|
||||
} = props;
|
||||
|
||||
const [isDraggingOverColumn, setIsDraggingOverColumn] = useState(false);
|
||||
const [dragColumnOrientation, setDragColumnOrientation] = useState<"justify-start" | "justify-end">("justify-start");
|
||||
const [isExpanded, setIsExpanded] = useState(true);
|
||||
const isExpanded = !(collapsedGroups?.group_by.includes(group.id))
|
||||
const groupRef = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
const { projectId } = useParams();
|
||||
@@ -129,10 +134,6 @@ export const ListGroup = observer((props: Props) => {
|
||||
return true;
|
||||
};
|
||||
|
||||
const toggleListGroup = () => {
|
||||
setIsExpanded((prevState) => !prevState);
|
||||
};
|
||||
|
||||
const prePopulateQuickAddData = (groupByKey: string | null, value: any) => {
|
||||
const defaultState = projectState.projectStates?.find((state) => state.default);
|
||||
let preloadedData: object = { state_id: defaultState?.id };
|
||||
@@ -213,6 +214,10 @@ export const ListGroup = observer((props: Props) => {
|
||||
handleOnDrop(source, destination);
|
||||
|
||||
highlightIssueOnDrop(getIssueBlockId(source.id, destination?.groupId), orderBy !== "sort_order");
|
||||
|
||||
if(!isExpanded){
|
||||
handleCollapsedGroups(group.id)
|
||||
}
|
||||
},
|
||||
})
|
||||
);
|
||||
@@ -248,7 +253,7 @@ export const ListGroup = observer((props: Props) => {
|
||||
disableIssueCreation={disableIssueCreation || isGroupByCreatedBy || isCompletedCycle}
|
||||
addIssuesToView={addIssuesToView}
|
||||
selectionHelpers={selectionHelpers}
|
||||
toggleListGroup={toggleListGroup}
|
||||
handleCollapsedGroups={handleCollapsedGroups}
|
||||
/>
|
||||
</Row>
|
||||
{shouldExpand && (
|
||||
|
||||
@@ -254,7 +254,7 @@ export class ArchivedIssuesFilter extends IssueFilterHelperStore implements IArc
|
||||
|
||||
const currentUserId = this.rootIssueStore.currentUserId;
|
||||
if (currentUserId)
|
||||
this.handleIssuesLocalFilters.set(EIssuesStoreType.PROJECT, type, workspaceSlug, projectId, undefined, {
|
||||
this.handleIssuesLocalFilters.set(EIssuesStoreType.ARCHIVED, type, workspaceSlug, projectId, undefined, {
|
||||
kanban_filters: _filters.kanbanFilters,
|
||||
});
|
||||
|
||||
|
||||
@@ -278,7 +278,7 @@ export class CycleIssuesFilter extends IssueFilterHelperStore implements ICycleI
|
||||
|
||||
const currentUserId = this.rootIssueStore.currentUserId;
|
||||
if (currentUserId)
|
||||
this.handleIssuesLocalFilters.set(EIssuesStoreType.PROJECT, type, workspaceSlug, cycleId, currentUserId, {
|
||||
this.handleIssuesLocalFilters.set(EIssuesStoreType.CYCLE, type, workspaceSlug, cycleId, currentUserId, {
|
||||
kanban_filters: _filters.kanbanFilters,
|
||||
});
|
||||
|
||||
|
||||
@@ -250,7 +250,7 @@ export class DraftIssuesFilter extends IssueFilterHelperStore implements IDraftI
|
||||
|
||||
const currentUserId = this.rootIssueStore.currentUserId;
|
||||
if (currentUserId)
|
||||
this.handleIssuesLocalFilters.set(EIssuesStoreType.PROJECT, type, workspaceSlug, projectId, undefined, {
|
||||
this.handleIssuesLocalFilters.set(EIssuesStoreType.DRAFT, type, workspaceSlug, projectId, undefined, {
|
||||
kanban_filters: _filters.kanbanFilters,
|
||||
});
|
||||
|
||||
|
||||
@@ -248,7 +248,7 @@ export class IssueFilterHelperStore implements IIssueFilterHelperStore {
|
||||
[filterType]: filters[filterType],
|
||||
},
|
||||
};
|
||||
|
||||
// All group_by "filters" are stored in a single array, will cause inconsistency in case of duplicated values
|
||||
storage.set("issue_local_filters", JSON.stringify(storageFilters));
|
||||
},
|
||||
};
|
||||
|
||||
@@ -281,7 +281,7 @@ export class ModuleIssuesFilter extends IssueFilterHelperStore implements IModul
|
||||
|
||||
const currentUserId = this.rootIssueStore.currentUserId;
|
||||
if (currentUserId)
|
||||
this.handleIssuesLocalFilters.set(EIssuesStoreType.PROJECT, type, workspaceSlug, moduleId, currentUserId, {
|
||||
this.handleIssuesLocalFilters.set(EIssuesStoreType.MODULE, type, workspaceSlug, moduleId, currentUserId, {
|
||||
kanban_filters: _filters.kanbanFilters,
|
||||
});
|
||||
|
||||
|
||||
@@ -252,7 +252,7 @@ export class ProfileIssuesFilter extends IssueFilterHelperStore implements IProf
|
||||
|
||||
const currentUserId = this.rootIssueStore.currentUserId;
|
||||
if (currentUserId)
|
||||
this.handleIssuesLocalFilters.set(EIssuesStoreType.PROJECT, type, workspaceSlug, userId, undefined, {
|
||||
this.handleIssuesLocalFilters.set(EIssuesStoreType.PROFILE, type, workspaceSlug, userId, undefined, {
|
||||
kanban_filters: _filters.kanbanFilters,
|
||||
});
|
||||
|
||||
|
||||
@@ -264,7 +264,7 @@ export class ProjectViewIssuesFilter extends IssueFilterHelperStore implements I
|
||||
|
||||
const currentUserId = this.rootIssueStore.currentUserId;
|
||||
if (currentUserId)
|
||||
this.handleIssuesLocalFilters.set(EIssuesStoreType.PROJECT, type, workspaceSlug, viewId, currentUserId, {
|
||||
this.handleIssuesLocalFilters.set(EIssuesStoreType.PROJECT_VIEW, type, workspaceSlug, viewId, currentUserId, {
|
||||
kanban_filters: _filters.kanbanFilters,
|
||||
});
|
||||
|
||||
|
||||
@@ -285,7 +285,7 @@ export class WorkspaceIssuesFilter extends IssueFilterHelperStore implements IWo
|
||||
|
||||
const currentUserId = this.rootIssueStore.currentUserId;
|
||||
if (currentUserId)
|
||||
this.handleIssuesLocalFilters.set(EIssuesStoreType.PROJECT, type, workspaceSlug, undefined, viewId, {
|
||||
this.handleIssuesLocalFilters.set(EIssuesStoreType.GLOBAL, type, workspaceSlug, undefined, viewId, {
|
||||
kanban_filters: _filters.kanbanFilters,
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user