From 73ffed3fd0e7694fe654102e313324d15b6757e7 Mon Sep 17 00:00:00 2001 From: rahulramesha Date: Wed, 7 Feb 2024 12:23:57 +0530 Subject: [PATCH] add logic to render all the issues at once --- web/components/core/render-if-visible-HOC.tsx | 24 +++++++++++--- .../issues/issue-layouts/kanban/block.tsx | 1 + .../issues/issue-layouts/list/default.tsx | 15 ++++----- .../spreadsheet/spreadsheet-table.tsx | 14 +++++--- web/hooks/use-virtualization-helper.tsx | 32 +++++++++++++++++++ 5 files changed, 70 insertions(+), 16 deletions(-) create mode 100644 web/hooks/use-virtualization-helper.tsx diff --git a/web/components/core/render-if-visible-HOC.tsx b/web/components/core/render-if-visible-HOC.tsx index d7c974956..10e911027 100644 --- a/web/components/core/render-if-visible-HOC.tsx +++ b/web/components/core/render-if-visible-HOC.tsx @@ -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) => { @@ -22,14 +26,26 @@ const RenderIfVisible: React.FC = (props) => { children, classNames = "", alwaysRender = false, - ...others + getShouldRender, + updateRenderTracker, + placeholderChildren = null, + index, } = props; - const [shouldVisible, setShouldVisible] = useState(alwaysRender); + const defaultVisible = !!getShouldRender && getShouldRender(index); + const [shouldVisible, setShouldVisible] = useState(alwaysRender || defaultVisible); const placeholderHeight = useRef(defaultHeight); const intersectionRef = useRef(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) => { } }, [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); }; diff --git a/web/components/issues/issue-layouts/kanban/block.tsx b/web/components/issues/issue-layouts/kanban/block.tsx index 7ada8535c..82079d632 100644 --- a/web/components/issues/issue-layouts/kanban/block.tsx +++ b/web/components/issues/issue-layouts/kanban/block.tsx @@ -139,6 +139,7 @@ export const KanbanIssueBlock: React.FC = memo((props) => { defaultHeight={100} horizonatlOffset={50} alwaysRender={snapshot.isDragging} + index={index} > = (props) => {
{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 = (props) => { defaultHeight={45} root={containerRef} classNames={"relative border border-transparent border-b-custom-border-200 last:border-b-transparent"} + index={index} > = (props) => {
); }; - - diff --git a/web/components/issues/issue-layouts/spreadsheet/spreadsheet-table.tsx b/web/components/issues/issue-layouts/spreadsheet/spreadsheet-table.tsx index 4db782cad..064517286 100644 --- a/web/components/issues/issue-layouts/spreadsheet/spreadsheet-table.tsx +++ b/web/components/issues/issue-layouts/spreadsheet/spreadsheet-table.tsx @@ -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} /> - {issueIds.map((id) => ( - + {issueIds.map((id, index) => ( + } + index={index} + > { + 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, + }; +};