add logic to render all the issues at once

This commit is contained in:
rahulramesha 2024-02-07 12:23:57 +05:30
parent 76808e6dc9
commit 73ffed3fd0
5 changed files with 70 additions and 16 deletions

View File

@ -10,6 +10,10 @@ type Props = {
as?: keyof JSX.IntrinsicElements;
classNames?: string;
alwaysRender?: boolean;
getShouldRender?: (index: number) => boolean;
updateRenderTracker?: (index: number, isVisble: boolean) => void;
placeholderChildren?: ReactNode;
index: number;
};
const RenderIfVisible: React.FC<Props> = (props) => {
@ -22,14 +26,26 @@ const RenderIfVisible: React.FC<Props> = (props) => {
children,
classNames = "",
alwaysRender = false,
...others
getShouldRender,
updateRenderTracker,
placeholderChildren = null,
index,
} = props;
const [shouldVisible, setShouldVisible] = useState<boolean>(alwaysRender);
const defaultVisible = !!getShouldRender && getShouldRender(index);
const [shouldVisible, setShouldVisible] = useState<boolean>(alwaysRender || defaultVisible);
const placeholderHeight = useRef<number>(defaultHeight);
const intersectionRef = useRef<HTMLElement | null>(null);
const isVisible = alwaysRender || shouldVisible;
useEffect(() => {
if (getShouldRender && getShouldRender(index)) setShouldVisible(true);
}, [getShouldRender, index]);
useEffect(() => {
updateRenderTracker && updateRenderTracker(index, shouldVisible);
}, [index, shouldVisible]);
// Set visibility with intersection observer
useEffect(() => {
if (intersectionRef.current) {
@ -64,9 +80,9 @@ const RenderIfVisible: React.FC<Props> = (props) => {
}
}, [isVisible, intersectionRef, alwaysRender]);
const child = isVisible ? <>{children}</> : null;
const child = isVisible ? <>{children}</> : placeholderChildren;
const style = isVisible ? {} : { height: placeholderHeight.current, width: "100%" };
const className = isVisible ? classNames : cn(classNames, "animate-pulse");
const className = isVisible ? classNames : cn(classNames, "animate-pulse bg-custom-background-80");
return React.createElement(as, { ref: intersectionRef, style, className }, child);
};

View File

@ -139,6 +139,7 @@ export const KanbanIssueBlock: React.FC<IssueBlockProps> = memo((props) => {
defaultHeight={100}
horizonatlOffset={50}
alwaysRender={snapshot.isDragging}
index={index}
>
<KanbanIssueDetailsBlock
issue={issue}

View File

@ -1,5 +1,8 @@
import { useRef } from "react";
// components
import { IssueBlock, IssueBlocksList, ListQuickAddIssueForm } from "components/issues";
import { IssueBlock, ListQuickAddIssueForm } from "components/issues";
import { HeaderGroupByCard } from "./headers/group-by-card";
import RenderIfVisible from "components/core/render-if-visible-HOC";
// hooks
import { useLabel, useMember, useProject, useProjectState } from "hooks/store";
// types
@ -14,11 +17,8 @@ import {
} from "@plane/types";
import { EIssueActions } from "../types";
// constants
import { HeaderGroupByCard } from "./headers/group-by-card";
import { getGroupByColumns, getIssueFlatList } from "../utils";
import { EIssueListRow, TCreateModalStoreTypes } from "constants/issue";
import { useRef } from "react";
import RenderIfVisible from "components/core/render-if-visible-HOC";
import { getGroupByColumns, getIssueFlatList } from "../utils";
export interface IGroupByList {
issueIds: TGroupedIssues | TUnGroupedIssues | any;
@ -108,7 +108,7 @@ const GroupByList: React.FC<IGroupByList> = (props) => {
<div ref={containerRef} className="relative overflow-auto h-full w-full">
{list &&
list.length > 0 &&
list.map((listRow: IIssueListRow) => {
list.map((listRow: IIssueListRow, index) => {
switch (listRow.type) {
case EIssueListRow.HEADER:
return (
@ -159,6 +159,7 @@ const GroupByList: React.FC<IGroupByList> = (props) => {
defaultHeight={45}
root={containerRef}
classNames={"relative border border-transparent border-b-custom-border-200 last:border-b-transparent"}
index={index}
>
<IssueBlock
issueId={listRow.id}
@ -237,5 +238,3 @@ export const List: React.FC<IList> = (props) => {
</div>
);
};

View File

@ -5,9 +5,8 @@ import { EIssueActions } from "../types";
//components
import { SpreadsheetIssueRow } from "./issue-row";
import { SpreadsheetHeader } from "./spreadsheet-header";
import { MutableRefObject, useRef } from "react";
import { MutableRefObject } from "react";
import RenderIfVisible from "components/core/render-if-visible-HOC";
import { cn } from "helpers/common.helper";
type Props = {
displayProperties: IIssueDisplayProperties;
@ -49,8 +48,15 @@ export const SpreadsheetTable = observer((props: Props) => {
isEstimateEnabled={isEstimateEnabled}
/>
<tbody>
{issueIds.map((id) => (
<RenderIfVisible key={id} as="tr" defaultHeight={44.5} root={containerRef}>
{issueIds.map((id, index) => (
<RenderIfVisible
key={id}
as="tr"
defaultHeight={44.5}
root={containerRef}
placeholderChildren={<td colSpan={100} className="border-b-[0.5px]" />}
index={index}
>
<SpreadsheetIssueRow
issueId={id}
displayProperties={displayProperties}

View File

@ -0,0 +1,32 @@
import { useRef } from "react";
const initializeRows = (rows: number) => {
const initailizedRows: { [id: number]: boolean } = {};
for (let i = 0; i < rows; ++i) initailizedRows[i] = true;
return initailizedRows;
};
const getMinMaxIndex = (renderedRows: { [id: number]: boolean }) => {
const rowIndexes = Object.keys(renderedRows).sort((a: string, b: string) => parseInt(a) - parseInt(b));
return { min: parseInt(rowIndexes[0]), max: parseInt(rowIndexes[rowIndexes.length - 1]) };
};
export const useVirtualizationHelper = (defaultNumberOfRows: number) => {
const renderedRows = useRef<{ [id: number]: boolean }>(initializeRows(defaultNumberOfRows));
const getShouldRender = (index: number) => {
const { min, max } = getMinMaxIndex(renderedRows.current);
return min !== undefined && max !== undefined && index !== undefined && index >= min && max >= index;
};
const updateRenderTracker = (index: number, isVisble: boolean) => {
if (isVisble) renderedRows.current[index] = true;
else if (renderedRows.current[index]) delete renderedRows.current[index];
};
return {
getShouldRender,
updateRenderTracker,
};
};