1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-02-14 00:19:16 +01:00

feat: Virtualized table with parent ref (#3993)

This commit is contained in:
Mateusz Kwasniewski 2023-06-15 14:11:04 +02:00 committed by GitHub
parent 221e3218df
commit c7ff3b472e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 58 additions and 19 deletions

View File

@ -1,4 +1,4 @@
import { useMemo } from 'react';
import { RefObject, useMemo } from 'react';
import { useTheme, TableBody, TableRow } from '@mui/material';
import { SortableTableHeader } from 'component/common/Table/SortableTableHeader/SortableTableHeader';
import { TableCell } from 'component/common/Table/TableCell/TableCell';
@ -21,11 +21,13 @@ export const VirtualizedTable = <T extends object>({
headerGroups,
rows,
prepareRow,
parentRef,
}: {
rowHeight?: number;
headerGroups: HeaderGroup<T>[];
rows: Row<T>[];
prepareRow: (row: Row<T>) => void;
parentRef?: RefObject<HTMLElement | null>;
}) => {
const theme = useTheme();
const rowHeight = useMemo(
@ -33,8 +35,12 @@ export const VirtualizedTable = <T extends object>({
[rowHeightOverride, theme.shape.tableRowHeight]
);
const [firstRenderedIndex, lastRenderedIndex] =
useVirtualizedRange(rowHeight);
const [firstRenderedIndex, lastRenderedIndex] = useVirtualizedRange(
rowHeight,
40,
5,
parentRef?.current
);
const tableHeight = useMemo(
() => rowHeight * rows.length + theme.shape.tableRowHeightCompact,

View File

@ -1,5 +1,12 @@
import { ConditionallyRender } from '../../../../common/ConditionallyRender/ConditionallyRender';
import { Box, IconButton, Popover, styled, useTheme } from '@mui/material';
import {
Box,
IconButton,
Popover,
styled,
Typography,
useTheme,
} from '@mui/material';
import { flexRow } from '../../../../../themes/themeStyles';
import { PlaygroundResultChip } from '../../PlaygroundResultsTable/PlaygroundResultChip/PlaygroundResultChip';
import { InfoOutlined } from '@mui/icons-material';
@ -78,6 +85,7 @@ export const AdvancedPlaygroundEnvironmentCell = ({
PaperProps={{
sx: {
borderRadius: `${theme.shape.borderRadiusLarge}px`,
padding: theme.spacing(3),
},
}}
onClose={onClose}
@ -87,6 +95,9 @@ export const AdvancedPlaygroundEnvironmentCell = ({
horizontal: -320,
}}
>
<Typography variant="subtitle2" sx={{ mb: 3 }}>
{value[0].environment}
</Typography>
<PlaygroundEnvironmentTable features={value} />
</Popover>
</>

View File

@ -1,4 +1,4 @@
import { useMemo } from 'react';
import React, { useMemo, useRef } from 'react';
import {
useFlexLayout,
useGlobalFilter,
@ -12,7 +12,7 @@ import {
AdvancedPlaygroundEnvironmentFeatureSchema,
PlaygroundFeatureSchema,
} from 'openapi';
import { useMediaQuery, useTheme } from '@mui/material';
import { Box, useMediaQuery, useTheme } from '@mui/material';
import { useConditionallyHiddenColumns } from 'hooks/useConditionallyHiddenColumns';
import { FeatureStatusCell } from '../PlaygroundResultsTable/FeatureStatusCell/FeatureStatusCell';
import { FeatureResultInfoPopoverCell } from '../PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureResultInfoPopoverCell';
@ -125,11 +125,22 @@ export const PlaygroundEnvironmentTable = ({
COLUMNS
);
const parentRef = useRef<HTMLElement | null>(null);
return (
<VirtualizedTable
rows={rows}
headerGroups={headerGroups}
prepareRow={prepareRow}
/>
<Box
ref={parentRef}
sx={{
overflow: 'auto',
maxHeight: '800px',
}}
>
<VirtualizedTable
parentRef={parentRef}
rows={rows}
headerGroups={headerGroups}
prepareRow={prepareRow}
/>
</Box>
);
};

View File

@ -54,7 +54,7 @@ export const resolveResultsWidth = (
}
if (results && !matches) {
return '65%';
return '60%';
}
return '50%';

View File

@ -12,27 +12,38 @@ import { useEffect, useState } from 'react';
export const useVirtualizedRange = (
rowHeight: number,
scrollOffset = 40,
dampening = 5
dampening = 5,
parentElement?: HTMLElement | null
) => {
const parent = parentElement ? parentElement : window;
const [scrollIndex, setScrollIndex] = useState(
Math.floor(window.pageYOffset / rowHeight)
Math.floor(
(parent instanceof HTMLElement
? parent.scrollTop
: parent.pageYOffset) / rowHeight
)
);
useEffect(() => {
const handleScroll = () => {
requestAnimationFrame(() => {
setScrollIndex(
Math.floor(window.pageYOffset / (rowHeight * dampening)) *
dampening
Math.floor(
(parent instanceof HTMLElement
? parent.scrollTop
: parent.pageYOffset) /
(rowHeight * dampening)
) * dampening
);
});
};
window.addEventListener('scroll', handleScroll, { passive: true });
parent.addEventListener('scroll', handleScroll, { passive: true });
return () => {
window.removeEventListener('scroll', handleScroll);
parent.removeEventListener('scroll', handleScroll);
};
}, [rowHeight, dampening]);
}, [rowHeight, dampening, parent]);
return [scrollIndex - scrollOffset, scrollIndex + scrollOffset] as const;
};