From 29d2db0f8e9ada58c1a6f98f25edaa3d4473ccb3 Mon Sep 17 00:00:00 2001 From: dekzter Date: Thu, 24 Apr 2025 11:20:36 -0400 Subject: [PATCH] testing out virtualized ,fixed some more bugs --- frontend/package-lock.json | 34 +++++ frontend/package.json | 1 + .../src/components/tables/ChannelsTable.jsx | 12 +- .../tables/CustomTable/CustomTable.jsx | 2 + .../tables/CustomTable/CustomTableBody.jsx | 128 +++++++++++++----- .../components/tables/CustomTable/index.jsx | 2 + frontend/src/pages/Settings.jsx | 1 + 7 files changed, 138 insertions(+), 42 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index f1caa9f6..d8da7f76 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -36,6 +36,7 @@ "react-draggable": "^4.4.6", "react-pro-sidebar": "^1.1.0", "react-router-dom": "^7.3.0", + "react-virtualized": "^9.22.6", "react-virtualized-auto-sizer": "^1.0.26", "react-window": "^1.8.11", "recharts": "^2.15.1", @@ -3207,6 +3208,12 @@ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "license": "MIT" }, + "node_modules/react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==", + "license": "MIT" + }, "node_modules/react-number-format": { "version": "5.4.3", "resolved": "https://registry.npmjs.org/react-number-format/-/react-number-format-5.4.3.tgz", @@ -3390,6 +3397,24 @@ "react-dom": ">=16.6.0" } }, + "node_modules/react-virtualized": { + "version": "9.22.6", + "resolved": "https://registry.npmjs.org/react-virtualized/-/react-virtualized-9.22.6.tgz", + "integrity": "sha512-U5j7KuUQt3AaMatlMJ0UJddqSiX+Km0YJxSqbAzIiGw5EmNz0khMyqP2hzgu4+QUtm+QPIrxzUX4raJxmVJnHg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.7.2", + "clsx": "^1.0.4", + "dom-helpers": "^5.1.3", + "loose-envify": "^1.4.0", + "prop-types": "^15.7.2", + "react-lifecycles-compat": "^3.0.4" + }, + "peerDependencies": { + "react": "^16.3.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.3.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/react-virtualized-auto-sizer": { "version": "1.0.26", "resolved": "https://registry.npmjs.org/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.26.tgz", @@ -3400,6 +3425,15 @@ "react-dom": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, + "node_modules/react-virtualized/node_modules/clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/react-window": { "version": "1.8.11", "resolved": "https://registry.npmjs.org/react-window/-/react-window-1.8.11.tgz", diff --git a/frontend/package.json b/frontend/package.json index 7af7ff89..3b287d79 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -38,6 +38,7 @@ "react-draggable": "^4.4.6", "react-pro-sidebar": "^1.1.0", "react-router-dom": "^7.3.0", + "react-virtualized": "^9.22.6", "react-virtualized-auto-sizer": "^1.0.26", "react-window": "^1.8.11", "recharts": "^2.15.1", diff --git a/frontend/src/components/tables/ChannelsTable.jsx b/frontend/src/components/tables/ChannelsTable.jsx index e819f13a..f12d555b 100644 --- a/frontend/src/components/tables/ChannelsTable.jsx +++ b/frontend/src/components/tables/ChannelsTable.jsx @@ -523,7 +523,7 @@ const ChannelsTable = ({}) => { header: () => #, cell: ({ getValue }) => ( - {getValue()} + {getValue()} ), }, @@ -545,7 +545,7 @@ const ChannelsTable = ({}) => { { id: 'channel_group', accessorFn: (row) => - row.channel_group_id && channelGroups + channelGroups[row.channel_group_id] ? channelGroups[row.channel_group_id].name : '', cell: ({ getValue }) => ( @@ -556,7 +556,7 @@ const ChannelsTable = ({}) => { textOverflow: 'ellipsis', }} > - {getValue()} + {getValue()} ), }, @@ -596,7 +596,7 @@ const ChannelsTable = ({}) => { ), }, ], - [selectedProfileId, data, channelGroups] + [selectedProfileId] ); const renderHeaderCell = (header) => { @@ -685,7 +685,9 @@ const ChannelsTable = ({}) => { manualFiltering: true, enableRowSelection: true, onRowSelectionChange: onRowSelectionChange, - getCoreRowModel: getCoreRowModel(), + getExpandedRowHeight: (row) => { + return 20 + 28 * row.original.streams.length; + }, expandedRowRenderer: ({ row }) => { return ( { className="divTable table-striped" style={{ width: '100%', + height: '100%', display: 'flex', flexDirection: 'column', }} @@ -31,6 +32,7 @@ const CustomTable = ({ table }) => { expandedRowIds={table.expandedRowIds} expandedRowRenderer={table.expandedRowRenderer} renderBodyCell={table.renderBodyCell} + getExpandedRowHeight={table.getExpandedRowHeight} /> ); diff --git a/frontend/src/components/tables/CustomTable/CustomTableBody.jsx b/frontend/src/components/tables/CustomTable/CustomTableBody.jsx index ad523a93..ac7000d3 100644 --- a/frontend/src/components/tables/CustomTable/CustomTableBody.jsx +++ b/frontend/src/components/tables/CustomTable/CustomTableBody.jsx @@ -1,11 +1,13 @@ import { Box, Flex } from '@mantine/core'; -import { flexRender } from '@tanstack/react-table'; +import { VariableSizeList as List } from 'react-window'; +import AutoSizer from 'react-virtualized-auto-sizer'; const CustomTableBody = ({ getRowModel, expandedRowIds, expandedRowRenderer, renderBodyCell, + getExpandedRowHeight, }) => { const renderExpandedRow = (row) => { if (expandedRowRenderer) { @@ -17,46 +19,98 @@ const CustomTableBody = ({ const rows = getRowModel().rows; - return ( - - {rows.map((row, index) => ( - - - {row.getVisibleCells().map((cell) => { + const renderTableBodyContents = () => { + const virtualized = false; + + if (virtualized) { + return ( + + + {({ height }) => { + const getItemSize = (index) => { + const row = rows[index]; + const isExpanded = expandedRowIds.includes(row.original.id); + console.log(isExpanded); + + // Default row height + let rowHeight = 28; + + if (isExpanded && getExpandedRowHeight) { + // If row is expanded, adjust the height to be larger (based on your logic) + // You can get this height from your state, or calculate based on number of items in the expanded row + rowHeight += getExpandedRowHeight(row); // This function would calculate the expanded row's height + } + + return rowHeight; + }; + return ( - - - {renderBodyCell({ row, cell })} - - + {({ index, style }) => { + const row = rows[index]; + return renderTableBodyRow(row, index, style); + }} + ); - })} - - {expandedRowIds.includes(row.original.id) && renderExpandedRow(row)} + }} + - ))} - - ); + ); + } + + return ( + + {rows.map((row, index) => renderTableBodyRow(row, index))} + + ); + }; + + const renderTableBodyRow = (row, index, style = {}) => { + return ( + + + {row.getVisibleCells().map((cell) => { + return ( + + + {renderBodyCell({ row, cell })} + + + ); + })} + + {expandedRowIds.includes(row.original.id) && renderExpandedRow(row)} + + ); + }; + + return renderTableBodyContents(); }; export default CustomTableBody; diff --git a/frontend/src/components/tables/CustomTable/index.jsx b/frontend/src/components/tables/CustomTable/index.jsx index 2e12ea30..7be3a8e7 100644 --- a/frontend/src/components/tables/CustomTable/index.jsx +++ b/frontend/src/components/tables/CustomTable/index.jsx @@ -16,6 +16,7 @@ const useTable = ({ bodyCellRenderFns = {}, expandedRowRenderer = () => <>, onRowSelectionChange = null, + getExpandedRowHeight = null, ...options }) => { const [selectedTableIds, setSelectedTableIds] = useState([]); @@ -145,6 +146,7 @@ const useTable = ({ headerCellRenderFns, bodyCellRenderFns, renderBodyCell, + getExpandedRowHeight, }; }; diff --git a/frontend/src/pages/Settings.jsx b/frontend/src/pages/Settings.jsx index 74329880..d9f716db 100644 --- a/frontend/src/pages/Settings.jsx +++ b/frontend/src/pages/Settings.jsx @@ -19,6 +19,7 @@ import { import { isNotEmpty, useForm } from '@mantine/form'; import UserAgentsTable from '../components/tables/UserAgentsTable'; import StreamProfilesTable from '../components/tables/StreamProfilesTable'; +import { useLocalStorage } from '@mantine/hooks'; const SettingsPage = () => { const settings = useSettingsStore((s) => s.settings);