Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: virtualization ish behaviour for issue layouts #3538

Merged
merged 18 commits into from
Feb 9, 2024
Merged
Changes from 1 commit
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Virtualization like changes for kanban
rahulramesha committed Feb 1, 2024
commit 76808e6dc9a0746e55b2235e0961148d222958b3
12 changes: 9 additions & 3 deletions web/components/issues/issue-layouts/kanban/base-kanban-root.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FC, useCallback, useState } from "react";
import { FC, useCallback, useRef, useState } from "react";
import { DragDropContext, DragStart, DraggableLocation, DropResult, Droppable } from "@hello-pangea/dnd";
import { useRouter } from "next/router";
import { observer } from "mobx-react-lite";
@@ -91,6 +91,8 @@ export const BaseKanBanRoot: React.FC<IBaseKanBanLayout> = observer((props: IBas

const { enableInlineEditing, enableQuickAdd, enableIssueCreation } = issues?.viewFlags || {};

const scrollableContainerRef = useRef<HTMLDivElement | null>(null);

// states
const [isDragStarted, setIsDragStarted] = useState<boolean>(false);
const [dragState, setDragState] = useState<KanbanDragState>({});
@@ -236,8 +238,11 @@ export const BaseKanBanRoot: React.FC<IBaseKanBanLayout> = observer((props: IBas
</div>
)}

<div className="horizontal-scroll-enable relative h-full w-full overflow-auto bg-custom-background-90">
<div className="relative h-full w-max min-w-full bg-custom-background-90 px-2">
<div
className="horizontal-scroll-enable relative h-full w-full overflow-auto bg-custom-background-90"
ref={scrollableContainerRef}
>
<div className="relative h-max w-max min-w-full bg-custom-background-90 px-2">
<DragDropContext onDragStart={onDragStart} onDragEnd={onDragEnd}>
{/* drag and delete component */}
<div
@@ -280,6 +285,7 @@ export const BaseKanBanRoot: React.FC<IBaseKanBanLayout> = observer((props: IBas
canEditProperties={canEditProperties}
storeType={storeType}
addIssuesToView={addIssuesToView}
scrollableContainerRef={scrollableContainerRef}
/>
</DragDropContext>
</div>
32 changes: 20 additions & 12 deletions web/components/issues/issue-layouts/kanban/block.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { memo } from "react";
import { MutableRefObject, memo } from "react";
import { Draggable, DraggableProvided, DraggableStateSnapshot } from "@hello-pangea/dnd";
import { observer } from "mobx-react-lite";
// hooks
@@ -13,6 +13,7 @@ import { TIssue, IIssueDisplayProperties, IIssueMap } from "@plane/types";
import { EIssueActions } from "../types";
// helper
import { cn } from "helpers/common.helper";
import RenderIfVisible from "components/core/render-if-visible-HOC";

interface IssueBlockProps {
peekIssueId?: string;
@@ -25,6 +26,7 @@ interface IssueBlockProps {
handleIssues: (issue: TIssue, action: EIssueActions) => void;
quickActions: (issue: TIssue) => React.ReactNode;
canEditProperties: (projectId: string | undefined) => boolean;
scrollableContainerRef?: MutableRefObject<HTMLDivElement | null>;
}

interface IssueDetailsBlockProps {
@@ -100,6 +102,7 @@ export const KanbanIssueBlock: React.FC<IssueBlockProps> = memo((props) => {
handleIssues,
quickActions,
canEditProperties,
scrollableContainerRef,
} = props;

const issue = issuesMap[issueId];
@@ -122,24 +125,29 @@ export const KanbanIssueBlock: React.FC<IssueBlockProps> = memo((props) => {
{...provided.dragHandleProps}
ref={provided.innerRef}
>
{issue.tempId !== undefined && (
<div className="absolute left-0 top-0 z-[99999] h-full w-full animate-pulse bg-custom-background-100/20" />
)}
<div
className={cn(
"space-y-2 rounded border-[0.5px] border-custom-border-200 bg-custom-background-100 px-3 py-2 text-sm transition-all hover:border-custom-border-400",
"rounded border-[0.5px] border-custom-border-200 bg-custom-background-100 px-3 py-2 text-sm transition-all hover:border-custom-border-400",
{ "hover:cursor-grab": !isDragDisabled },
{ "border-custom-primary-100": snapshot.isDragging },
{ "border border-custom-primary-70 hover:border-custom-primary-70": peekIssueId === issue.id }
)}
>
<KanbanIssueDetailsBlock
issue={issue}
displayProperties={displayProperties}
handleIssues={handleIssues}
quickActions={quickActions}
isReadOnly={!canEditIssueProperties}
/>
<RenderIfVisible
classNames="space-y-2"
root={scrollableContainerRef}
defaultHeight={100}
horizonatlOffset={50}
alwaysRender={snapshot.isDragging}
>
<KanbanIssueDetailsBlock
issue={issue}
displayProperties={displayProperties}
handleIssues={handleIssues}
quickActions={quickActions}
isReadOnly={!canEditIssueProperties}
/>
</RenderIfVisible>
</div>
</div>
)}
5 changes: 4 additions & 1 deletion web/components/issues/issue-layouts/kanban/blocks-list.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { memo } from "react";
import { MutableRefObject, memo } from "react";
//types
import { TIssue, IIssueDisplayProperties, IIssueMap } from "@plane/types";
import { EIssueActions } from "../types";
@@ -16,6 +16,7 @@ interface IssueBlocksListProps {
handleIssues: (issue: TIssue, action: EIssueActions) => void;
quickActions: (issue: TIssue, customActionButton?: React.ReactElement) => React.ReactNode;
canEditProperties: (projectId: string | undefined) => boolean;
scrollableContainerRef?: MutableRefObject<HTMLDivElement | null>;
}

const KanbanIssueBlocksListMemo: React.FC<IssueBlocksListProps> = (props) => {
@@ -30,6 +31,7 @@ const KanbanIssueBlocksListMemo: React.FC<IssueBlocksListProps> = (props) => {
handleIssues,
quickActions,
canEditProperties,
scrollableContainerRef,
} = props;

return (
@@ -56,6 +58,7 @@ const KanbanIssueBlocksListMemo: React.FC<IssueBlocksListProps> = (props) => {
index={index}
isDragDisabled={isDragDisabled}
canEditProperties={canEditProperties}
scrollableContainerRef={scrollableContainerRef}
/>
);
})}
7 changes: 7 additions & 0 deletions web/components/issues/issue-layouts/kanban/default.tsx
Original file line number Diff line number Diff line change
@@ -20,6 +20,7 @@ import {
import { EIssueActions } from "../types";
import { getGroupByColumns } from "../utils";
import { TCreateModalStoreTypes } from "constants/issue";
import { MutableRefObject } from "react";

export interface IGroupByKanBan {
issuesMap: IIssueMap;
@@ -45,6 +46,7 @@ export interface IGroupByKanBan {
storeType?: TCreateModalStoreTypes;
addIssuesToView?: (issueIds: string[]) => Promise<TIssue>;
canEditProperties: (projectId: string | undefined) => boolean;
scrollableContainerRef?: MutableRefObject<HTMLDivElement | null>;
}

const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => {
@@ -67,6 +69,7 @@ const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => {
storeType,
addIssuesToView,
canEditProperties,
scrollableContainerRef,
} = props;

const member = useMember();
@@ -135,6 +138,7 @@ const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => {
disableIssueCreation={disableIssueCreation}
canEditProperties={canEditProperties}
groupByVisibilityToggle={groupByVisibilityToggle}
scrollableContainerRef={scrollableContainerRef}
/>
)}
</div>
@@ -168,6 +172,7 @@ export interface IKanBan {
storeType?: TCreateModalStoreTypes;
addIssuesToView?: (issueIds: string[]) => Promise<TIssue>;
canEditProperties: (projectId: string | undefined) => boolean;
scrollableContainerRef?: MutableRefObject<HTMLDivElement | null>;
}

export const KanBan: React.FC<IKanBan> = observer((props) => {
@@ -189,6 +194,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
storeType,
addIssuesToView,
canEditProperties,
scrollableContainerRef,
} = props;

const issueKanBanView = useKanbanView();
@@ -213,6 +219,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
storeType={storeType}
addIssuesToView={addIssuesToView}
canEditProperties={canEditProperties}
scrollableContainerRef={scrollableContainerRef}
/>
);
});
4 changes: 4 additions & 0 deletions web/components/issues/issue-layouts/kanban/kanban-group.tsx
Original file line number Diff line number Diff line change
@@ -13,6 +13,7 @@ import {
TUnGroupedIssues,
} from "@plane/types";
import { EIssueActions } from "../types";
import { MutableRefObject } from "react";

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

export const KanbanGroup = (props: IKanbanGroup) => {
@@ -57,6 +59,7 @@ export const KanbanGroup = (props: IKanbanGroup) => {
disableIssueCreation,
quickAddCallback,
viewId,
scrollableContainerRef,
} = props;
// hooks
const projectState = useProjectState();
@@ -127,6 +130,7 @@ export const KanbanGroup = (props: IKanbanGroup) => {
handleIssues={handleIssues}
quickActions={quickActions}
canEditProperties={canEditProperties}
scrollableContainerRef={scrollableContainerRef}
/>

{provided.placeholder}
7 changes: 7 additions & 0 deletions web/components/issues/issue-layouts/kanban/swimlanes.tsx
Original file line number Diff line number Diff line change
@@ -20,6 +20,7 @@ import { EIssueActions } from "../types";
import { useLabel, useMember, useProject, useProjectState } from "hooks/store";
import { getGroupByColumns } from "../utils";
import { TCreateModalStoreTypes } from "constants/issue";
import { MutableRefObject } from "react";

interface ISubGroupSwimlaneHeader {
issueIds: TGroupedIssues | TSubGroupedIssues | TUnGroupedIssues;
@@ -80,6 +81,7 @@ interface ISubGroupSwimlane extends ISubGroupSwimlaneHeader {
viewId?: string
) => Promise<TIssue | undefined>;
viewId?: string;
scrollableContainerRef?: MutableRefObject<HTMLDivElement | null>;
}
const SubGroupSwimlane: React.FC<ISubGroupSwimlane> = observer((props) => {
const {
@@ -99,6 +101,7 @@ const SubGroupSwimlane: React.FC<ISubGroupSwimlane> = observer((props) => {
addIssuesToView,
quickAddCallback,
viewId,
scrollableContainerRef,
} = props;

const calculateIssueCount = (column_id: string) => {
@@ -150,6 +153,7 @@ const SubGroupSwimlane: React.FC<ISubGroupSwimlane> = observer((props) => {
addIssuesToView={addIssuesToView}
quickAddCallback={quickAddCallback}
viewId={viewId}
scrollableContainerRef={scrollableContainerRef}
/>
</div>
)}
@@ -183,6 +187,7 @@ export interface IKanBanSwimLanes {
) => Promise<TIssue | undefined>;
viewId?: string;
canEditProperties: (projectId: string | undefined) => boolean;
scrollableContainerRef?: MutableRefObject<HTMLDivElement | null>;
}

export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
@@ -204,6 +209,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
addIssuesToView,
quickAddCallback,
viewId,
scrollableContainerRef,
} = props;

const member = useMember();
@@ -249,6 +255,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
canEditProperties={canEditProperties}
quickAddCallback={quickAddCallback}
viewId={viewId}
scrollableContainerRef={scrollableContainerRef}
/>
)}
</div>