From 9f2e980bf968ca466ace4f84fc537d5760d71185 Mon Sep 17 00:00:00 2001 From: Anton Standrik Date: Fri, 30 May 2025 12:17:55 +0300 Subject: [PATCH 1/6] fix: table is not scrolled to top on sorting --- .../PaginatedTableWithLayout.tsx | 39 ++++++++++++++++--- .../TableWithControlsLayout.tsx | 18 +++++++-- .../PaginatedNodes/GroupedNodesComponent.tsx | 32 +++++++++------ .../GroupedStorageGroupsComponent.tsx | 36 ++++++++++------- .../GroupedStorageNodesComponent.tsx | 38 +++++++++++------- src/containers/Tablets/TabletsTable.tsx | 15 ++++--- src/containers/Tenants/Tenants.tsx | 5 ++- 7 files changed, 125 insertions(+), 58 deletions(-) diff --git a/src/components/PaginatedTable/PaginatedTableWithLayout.tsx b/src/components/PaginatedTable/PaginatedTableWithLayout.tsx index 4525dc72a..adcc80205 100644 --- a/src/components/PaginatedTable/PaginatedTableWithLayout.tsx +++ b/src/components/PaginatedTable/PaginatedTableWithLayout.tsx @@ -3,11 +3,11 @@ import React from 'react'; import {TableWithControlsLayout} from '../TableWithControlsLayout/TableWithControlsLayout'; import type {TableProps} from '../TableWithControlsLayout/TableWithControlsLayout'; -import {PaginatedTableProvider} from './PaginatedTableContext'; +import {PaginatedTableProvider, usePaginatedTableState} from './PaginatedTableContext'; import type {PaginatedTableState} from './types'; export interface PaginatedTableWithLayoutProps { - controls: React.ReactNode; + controls?: React.ReactNode; table: React.ReactNode; tableProps?: TableProps; error?: React.ReactNode; @@ -16,6 +16,33 @@ export interface PaginatedTableWithLayoutProps { noBatching?: boolean; } +// Internal component that has access to the paginated table context +const TableWithAutoScrolling = ({ + table, + tableProps, +}: { + table: React.ReactNode; + tableProps?: TableProps; +}) => { + const {tableState} = usePaginatedTableState(); + const {sortParams} = tableState; + + // Enhance tableProps to include sortParams in scrollDependencies + const enhancedTableProps = React.useMemo( + () => ({ + ...tableProps, + scrollDependencies: [...(tableProps?.scrollDependencies || []), sortParams], + }), + [tableProps, sortParams], + ); + + return ( + + {table} + + ); +}; + export const PaginatedTableWithLayout = ({ controls, table, @@ -27,11 +54,11 @@ export const PaginatedTableWithLayout = ({ }: PaginatedTableWithLayoutProps) => ( - {controls} + {controls ? ( + {controls} + ) : null} {error} - - {table} - + ); diff --git a/src/components/TableWithControlsLayout/TableWithControlsLayout.tsx b/src/components/TableWithControlsLayout/TableWithControlsLayout.tsx index 6e644bad9..8b2c21725 100644 --- a/src/components/TableWithControlsLayout/TableWithControlsLayout.tsx +++ b/src/components/TableWithControlsLayout/TableWithControlsLayout.tsx @@ -18,10 +18,12 @@ interface TableWithControlsLayoutItemProps { fullHeight?: boolean; } -export interface TableProps extends TableWithControlsLayoutItemProps { +export interface TableProps extends Omit { loading?: boolean; scrollContainerRef?: React.RefObject; scrollDependencies?: any[]; + onSort?: (params: any) => void; + children?: React.ReactNode | ((props: {onSort: (params: any) => void}) => React.ReactNode); } export const TableWithControlsLayout = ({ @@ -56,24 +58,34 @@ TableWithControlsLayout.Table = function Table({ className, scrollContainerRef, scrollDependencies = [], + onSort, }: TableProps) { // Create an internal ref for the table container const tableContainerRef = React.useRef(null); // Use the internal ref for scrolling - useTableScroll({ + const {handleTableScroll} = useTableScroll({ tableContainerRef, scrollContainerRef, dependencies: scrollDependencies, }); + // Create a wrapper function that triggers scroll on sort + const handleSort = React.useCallback( + (params: any) => { + onSort?.(params); // Call original callback if provided + handleTableScroll(); // Trigger scroll to top + }, + [onSort, handleTableScroll], + ); + if (loading) { return ; } return (
- {children} + {typeof children === 'function' ? children({onSort: handleSort}) : children}
); }; diff --git a/src/containers/Nodes/PaginatedNodes/GroupedNodesComponent.tsx b/src/containers/Nodes/PaginatedNodes/GroupedNodesComponent.tsx index 315169757..8336d41b3 100644 --- a/src/containers/Nodes/PaginatedNodes/GroupedNodesComponent.tsx +++ b/src/containers/Nodes/PaginatedNodes/GroupedNodesComponent.tsx @@ -55,18 +55,26 @@ const NodeGroup = React.memo(function NodeGroup({ expanded={isExpanded} onIsExpandedChange={onIsExpandedChange} > - + } + tableProps={{ + scrollContainerRef: scrollContainerRef, + }} /> ); diff --git a/src/containers/Storage/PaginatedStorageGroups/GroupedStorageGroupsComponent.tsx b/src/containers/Storage/PaginatedStorageGroups/GroupedStorageGroupsComponent.tsx index cd748c64f..d33c8f48a 100644 --- a/src/containers/Storage/PaginatedStorageGroups/GroupedStorageGroupsComponent.tsx +++ b/src/containers/Storage/PaginatedStorageGroups/GroupedStorageGroupsComponent.tsx @@ -59,20 +59,28 @@ export const StorageGroupGroup = React.memo(function StorageGroupGroup({ expanded={isExpanded} onIsExpandedChange={onIsExpandedChange} > - + } + tableProps={{ + scrollContainerRef: scrollContainerRef, + }} /> ); diff --git a/src/containers/Storage/PaginatedStorageNodes/GroupedStorageNodesComponent.tsx b/src/containers/Storage/PaginatedStorageNodes/GroupedStorageNodesComponent.tsx index 20beaa867..ca172e372 100644 --- a/src/containers/Storage/PaginatedStorageNodes/GroupedStorageNodesComponent.tsx +++ b/src/containers/Storage/PaginatedStorageNodes/GroupedStorageNodesComponent.tsx @@ -60,21 +60,29 @@ export const StorageNodeGroup = React.memo(function StorageNodeGroup({ expanded={isExpanded} onIsExpandedChange={onIsExpandedChange} > - + } + tableProps={{ + scrollContainerRef: scrollContainerRef, + }} /> ); diff --git a/src/containers/Tablets/TabletsTable.tsx b/src/containers/Tablets/TabletsTable.tsx index aedc46242..d00a71594 100644 --- a/src/containers/Tablets/TabletsTable.tsx +++ b/src/containers/Tablets/TabletsTable.tsx @@ -217,12 +217,15 @@ export function TabletsTable({ scrollDependencies={[tabletsSearch]} loading={loading} > - + {({onSort}) => ( + + )} ); diff --git a/src/containers/Tenants/Tenants.tsx b/src/containers/Tenants/Tenants.tsx index 5c80ff820..fd49ec01c 100644 --- a/src/containers/Tenants/Tenants.tsx +++ b/src/containers/Tenants/Tenants.tsx @@ -128,7 +128,7 @@ export const Tenants = ({additionalTenantsProps, scrollContainerRef}: TenantsPro ); }; - const renderTable = () => { + const renderTable = (onSort?: (params: any) => void) => { const columns: Column[] = [ { name: 'Name', @@ -261,6 +261,7 @@ export const Tenants = ({additionalTenantsProps, scrollContainerRef}: TenantsPro columns={columns} settings={DEFAULT_TABLE_SETTINGS} emptyDataMessage="No such tenants" + onSort={onSort} /> ); }; @@ -277,7 +278,7 @@ export const Tenants = ({additionalTenantsProps, scrollContainerRef}: TenantsPro loading={loading} scrollDependencies={[searchValue, problemFilter]} > - {currentData ? renderTable() : null} + {({onSort}) => (currentData ? renderTable(onSort) : null)} From 8c963332270726ab55fcac582a125bbd073d12c3 Mon Sep 17 00:00:00 2001 From: Anton Standrik Date: Fri, 30 May 2025 12:37:36 +0300 Subject: [PATCH 2/6] fix: add comment --- .../TableWithControlsLayout/TableWithControlsLayout.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/TableWithControlsLayout/TableWithControlsLayout.tsx b/src/components/TableWithControlsLayout/TableWithControlsLayout.tsx index 8b2c21725..c1a6a6cdf 100644 --- a/src/components/TableWithControlsLayout/TableWithControlsLayout.tsx +++ b/src/components/TableWithControlsLayout/TableWithControlsLayout.tsx @@ -22,6 +22,8 @@ export interface TableProps extends Omit; scrollDependencies?: any[]; + + // onSort is called with the table's sort parameters and triggers auto-scrolling. onSort?: (params: any) => void; children?: React.ReactNode | ((props: {onSort: (params: any) => void}) => React.ReactNode); } From 4aa6df488d5be00c2f18abf421e80dd6a279d005 Mon Sep 17 00:00:00 2001 From: Anton Standrik Date: Mon, 2 Jun 2025 14:33:20 +0300 Subject: [PATCH 3/6] fix: better code --- .../PaginatedTableWithLayout.tsx | 105 +++++++++++++----- .../TableWithControlsLayout.tsx | 4 +- .../PaginatedNodes/GroupedNodesComponent.tsx | 5 +- .../Nodes/PaginatedNodes/NodesComponent.tsx | 3 +- .../GroupedStorageGroupsComponent.tsx | 4 +- .../StorageGroupsComponent.tsx | 3 +- .../GroupedStorageNodesComponent.tsx | 4 +- .../StorageNodesComponent.tsx | 3 +- .../Diagnostics/TopicData/TopicData.tsx | 3 +- 9 files changed, 87 insertions(+), 47 deletions(-) diff --git a/src/components/PaginatedTable/PaginatedTableWithLayout.tsx b/src/components/PaginatedTable/PaginatedTableWithLayout.tsx index adcc80205..7982776a8 100644 --- a/src/components/PaginatedTable/PaginatedTableWithLayout.tsx +++ b/src/components/PaginatedTable/PaginatedTableWithLayout.tsx @@ -1,7 +1,7 @@ import React from 'react'; import {TableWithControlsLayout} from '../TableWithControlsLayout/TableWithControlsLayout'; -import type {TableProps} from '../TableWithControlsLayout/TableWithControlsLayout'; +import type {TableWrapperProps} from '../TableWithControlsLayout/TableWithControlsLayout'; import {PaginatedTableProvider, usePaginatedTableState} from './PaginatedTableContext'; import type {PaginatedTableState} from './types'; @@ -9,56 +9,101 @@ import type {PaginatedTableState} from './types'; export interface PaginatedTableWithLayoutProps { controls?: React.ReactNode; table: React.ReactNode; - tableProps?: TableProps; + tableWrapperProps?: TableWrapperProps; error?: React.ReactNode; initialState?: Partial; fullHeight?: boolean; noBatching?: boolean; } -// Internal component that has access to the paginated table context -const TableWithAutoScrolling = ({ +/** + * Hook to enhance table wrapper props with sort-dependent scroll behavior + */ +const useTableWrapperPropsWithSortDependency = ( + tableWrapperProps?: TableWrapperProps, +): TableWrapperProps => { + const {tableState} = usePaginatedTableState(); + const {sortParams} = tableState; + + return React.useMemo(() => { + const existingScrollDependencies = tableWrapperProps?.scrollDependencies || []; + + return { + ...tableWrapperProps, + scrollDependencies: [...existingScrollDependencies, sortParams], + }; + }, [tableWrapperProps, sortParams]); +}; + +/** + * Internal component that wraps the table with sort-dependent scrolling behavior. + * This component has access to the paginated table context and automatically + * scrolls to top when sort parameters change. + */ +const TableWrapper = ({ table, - tableProps, + tableWrapperProps, }: { table: React.ReactNode; - tableProps?: TableProps; + tableWrapperProps?: TableWrapperProps; }) => { - const {tableState} = usePaginatedTableState(); - const {sortParams} = tableState; - - // Enhance tableProps to include sortParams in scrollDependencies - const enhancedTableProps = React.useMemo( - () => ({ - ...tableProps, - scrollDependencies: [...(tableProps?.scrollDependencies || []), sortParams], - }), - [tableProps, sortParams], - ); + const enhancedTableWrapperProps = useTableWrapperPropsWithSortDependency(tableWrapperProps); return ( - + {table} ); }; +/** + * Renders the controls section if controls are provided + */ +const ControlsSection = ({controls}: {controls?: React.ReactNode}) => { + if (!controls) { + return null; + } + + return {controls}; +}; + +/** + * Renders the error section if an error is provided + */ +const ErrorSection = ({error}: {error?: React.ReactNode}) => { + if (!error) { + return null; + } + + return {error}; +}; + +/** + * A complete table layout component that provides pagination context and + * integrates with TableWithControlsLayout for consistent styling and behavior. + * + * Features: + * - Provides pagination context to child components + * - Automatic scroll-to-top on sort changes + * - Optional controls and error display + * - Configurable height behavior + */ export const PaginatedTableWithLayout = ({ controls, table, - tableProps, + tableWrapperProps, error, initialState, noBatching, fullHeight = true, -}: PaginatedTableWithLayoutProps) => ( - - - {controls ? ( - {controls} - ) : null} - {error} - - - -); +}: PaginatedTableWithLayoutProps) => { + return ( + + + + + + + + ); +}; diff --git a/src/components/TableWithControlsLayout/TableWithControlsLayout.tsx b/src/components/TableWithControlsLayout/TableWithControlsLayout.tsx index c1a6a6cdf..bc3cef0fd 100644 --- a/src/components/TableWithControlsLayout/TableWithControlsLayout.tsx +++ b/src/components/TableWithControlsLayout/TableWithControlsLayout.tsx @@ -18,7 +18,7 @@ interface TableWithControlsLayoutItemProps { fullHeight?: boolean; } -export interface TableProps extends Omit { +export interface TableWrapperProps extends Omit { loading?: boolean; scrollContainerRef?: React.RefObject; scrollDependencies?: any[]; @@ -61,7 +61,7 @@ TableWithControlsLayout.Table = function Table({ scrollContainerRef, scrollDependencies = [], onSort, -}: TableProps) { +}: TableWrapperProps) { // Create an internal ref for the table container const tableContainerRef = React.useRef(null); diff --git a/src/containers/Nodes/PaginatedNodes/GroupedNodesComponent.tsx b/src/containers/Nodes/PaginatedNodes/GroupedNodesComponent.tsx index 8336d41b3..c65f263bc 100644 --- a/src/containers/Nodes/PaginatedNodes/GroupedNodesComponent.tsx +++ b/src/containers/Nodes/PaginatedNodes/GroupedNodesComponent.tsx @@ -72,7 +72,7 @@ const NodeGroup = React.memo(function NodeGroup({ scrollContainerRef={scrollContainerRef} /> } - tableProps={{ + tableWrapperProps={{ scrollContainerRef: scrollContainerRef, }} /> @@ -192,13 +192,12 @@ export function GroupedNodesComponent({ } error={error ? : null} table={renderGroups()} - tableProps={{ + tableWrapperProps={{ scrollContainerRef, scrollDependencies: [searchValue, groupByParam, tableGroups, peerRoleFilter], loading: isLoading, className: b('groups-wrapper'), }} - fullHeight /> ); } diff --git a/src/containers/Nodes/PaginatedNodes/NodesComponent.tsx b/src/containers/Nodes/PaginatedNodes/NodesComponent.tsx index 34b8bbb87..7f05e879c 100644 --- a/src/containers/Nodes/PaginatedNodes/NodesComponent.tsx +++ b/src/containers/Nodes/PaginatedNodes/NodesComponent.tsx @@ -72,11 +72,10 @@ export function NodesComponent({ scrollContainerRef={scrollContainerRef} /> } - tableProps={{ + tableWrapperProps={{ scrollContainerRef, scrollDependencies: [searchValue, problemFilter, uptimeFilter, peerRoleFilter], }} - fullHeight /> ); } diff --git a/src/containers/Storage/PaginatedStorageGroups/GroupedStorageGroupsComponent.tsx b/src/containers/Storage/PaginatedStorageGroups/GroupedStorageGroupsComponent.tsx index d33c8f48a..41c674e89 100644 --- a/src/containers/Storage/PaginatedStorageGroups/GroupedStorageGroupsComponent.tsx +++ b/src/containers/Storage/PaginatedStorageGroups/GroupedStorageGroupsComponent.tsx @@ -78,7 +78,7 @@ export const StorageGroupGroup = React.memo(function StorageGroupGroup({ initialEntitiesCount={count} /> } - tableProps={{ + tableWrapperProps={{ scrollContainerRef: scrollContainerRef, }} /> @@ -181,7 +181,7 @@ export function GroupedStorageGroupsComponent({ error={error ? : null} table={renderGroups()} initialState={initialState} - tableProps={{ + tableWrapperProps={{ scrollContainerRef, scrollDependencies: [searchValue, storageGroupsGroupByParam, tableGroups], loading: isLoading, diff --git a/src/containers/Storage/PaginatedStorageGroups/StorageGroupsComponent.tsx b/src/containers/Storage/PaginatedStorageGroups/StorageGroupsComponent.tsx index 0864a81c6..0ecb6488b 100644 --- a/src/containers/Storage/PaginatedStorageGroups/StorageGroupsComponent.tsx +++ b/src/containers/Storage/PaginatedStorageGroups/StorageGroupsComponent.tsx @@ -51,11 +51,10 @@ export function StorageGroupsComponent({ initialEntitiesCount={initialEntitiesCount} /> } - tableProps={{ + tableWrapperProps={{ scrollContainerRef, scrollDependencies: [searchValue, visibleEntities], }} - fullHeight /> ); } diff --git a/src/containers/Storage/PaginatedStorageNodes/GroupedStorageNodesComponent.tsx b/src/containers/Storage/PaginatedStorageNodes/GroupedStorageNodesComponent.tsx index ca172e372..320c8cb1b 100644 --- a/src/containers/Storage/PaginatedStorageNodes/GroupedStorageNodesComponent.tsx +++ b/src/containers/Storage/PaginatedStorageNodes/GroupedStorageNodesComponent.tsx @@ -80,7 +80,7 @@ export const StorageNodeGroup = React.memo(function StorageNodeGroup({ onDataFetched={onDataFetched} /> } - tableProps={{ + tableWrapperProps={{ scrollContainerRef: scrollContainerRef, }} /> @@ -182,7 +182,7 @@ export function GroupedStorageNodesComponent({ error={error ? : null} table={renderGroups()} initialState={initialState} - tableProps={{ + tableWrapperProps={{ scrollContainerRef, scrollDependencies: [searchValue, storageNodesGroupByParam, tableGroups], loading: isLoading, diff --git a/src/containers/Storage/PaginatedStorageNodes/StorageNodesComponent.tsx b/src/containers/Storage/PaginatedStorageNodes/StorageNodesComponent.tsx index d0c155f9c..5869af50d 100644 --- a/src/containers/Storage/PaginatedStorageNodes/StorageNodesComponent.tsx +++ b/src/containers/Storage/PaginatedStorageNodes/StorageNodesComponent.tsx @@ -56,11 +56,10 @@ export function StorageNodesComponent({ onDataFetched={handleDataFetched} /> } - tableProps={{ + tableWrapperProps={{ scrollContainerRef, scrollDependencies: [searchValue, visibleEntities, nodesUptimeFilter], }} - fullHeight /> ); } diff --git a/src/containers/Tenant/Diagnostics/TopicData/TopicData.tsx b/src/containers/Tenant/Diagnostics/TopicData/TopicData.tsx index 90e372a29..168088b9b 100644 --- a/src/containers/Tenant/Diagnostics/TopicData/TopicData.tsx +++ b/src/containers/Tenant/Diagnostics/TopicData/TopicData.tsx @@ -343,11 +343,10 @@ export function TopicData({scrollContainerRef, path, database}: TopicDataProps) }} /> } - tableProps={{ + tableWrapperProps={{ scrollContainerRef, scrollDependencies: [baseOffset, baseEndOffset, tableFilters], }} - fullHeight noBatching /> From d5935a495cf6e1489a37fe59ad22be2a6c02bb86 Mon Sep 17 00:00:00 2001 From: Anton Standrik Date: Mon, 2 Jun 2025 14:39:42 +0300 Subject: [PATCH 4/6] fix: better code --- .../PaginatedTableWithLayout.tsx | 46 ++++--------------- 1 file changed, 8 insertions(+), 38 deletions(-) diff --git a/src/components/PaginatedTable/PaginatedTableWithLayout.tsx b/src/components/PaginatedTable/PaginatedTableWithLayout.tsx index 7982776a8..d9c930f0b 100644 --- a/src/components/PaginatedTable/PaginatedTableWithLayout.tsx +++ b/src/components/PaginatedTable/PaginatedTableWithLayout.tsx @@ -16,16 +16,17 @@ export interface PaginatedTableWithLayoutProps { noBatching?: boolean; } -/** - * Hook to enhance table wrapper props with sort-dependent scroll behavior - */ -const useTableWrapperPropsWithSortDependency = ( - tableWrapperProps?: TableWrapperProps, -): TableWrapperProps => { +const TableWrapper = ({ + table, + tableWrapperProps, +}: { + table: React.ReactNode; + tableWrapperProps?: TableWrapperProps; +}) => { const {tableState} = usePaginatedTableState(); const {sortParams} = tableState; - return React.useMemo(() => { + const enhancedTableWrapperProps = React.useMemo(() => { const existingScrollDependencies = tableWrapperProps?.scrollDependencies || []; return { @@ -33,21 +34,6 @@ const useTableWrapperPropsWithSortDependency = ( scrollDependencies: [...existingScrollDependencies, sortParams], }; }, [tableWrapperProps, sortParams]); -}; - -/** - * Internal component that wraps the table with sort-dependent scrolling behavior. - * This component has access to the paginated table context and automatically - * scrolls to top when sort parameters change. - */ -const TableWrapper = ({ - table, - tableWrapperProps, -}: { - table: React.ReactNode; - tableWrapperProps?: TableWrapperProps; -}) => { - const enhancedTableWrapperProps = useTableWrapperPropsWithSortDependency(tableWrapperProps); return ( @@ -56,9 +42,6 @@ const TableWrapper = ({ ); }; -/** - * Renders the controls section if controls are provided - */ const ControlsSection = ({controls}: {controls?: React.ReactNode}) => { if (!controls) { return null; @@ -67,9 +50,6 @@ const ControlsSection = ({controls}: {controls?: React.ReactNode}) => { return {controls}; }; -/** - * Renders the error section if an error is provided - */ const ErrorSection = ({error}: {error?: React.ReactNode}) => { if (!error) { return null; @@ -78,16 +58,6 @@ const ErrorSection = ({error}: {error?: React.ReactNode}) => { return {error}; }; -/** - * A complete table layout component that provides pagination context and - * integrates with TableWithControlsLayout for consistent styling and behavior. - * - * Features: - * - Provides pagination context to child components - * - Automatic scroll-to-top on sort changes - * - Optional controls and error display - * - Configurable height behavior - */ export const PaginatedTableWithLayout = ({ controls, table, From c2197511e857cd6d32f7618f9a6f57057de03e17 Mon Sep 17 00:00:00 2001 From: Anton Standrik Date: Mon, 2 Jun 2025 16:53:30 +0300 Subject: [PATCH 5/6] fix: better code --- .../PaginatedTableWithLayout.tsx | 4 ++-- .../ResizeableDataTable.tsx | 14 +++++++++++++ .../TableWithControlsLayout.tsx | 21 ++++--------------- src/containers/Tablets/TabletsTable.tsx | 21 ++++++++++--------- src/containers/Tenants/Tenants.tsx | 11 ++++++---- 5 files changed, 38 insertions(+), 33 deletions(-) diff --git a/src/components/PaginatedTable/PaginatedTableWithLayout.tsx b/src/components/PaginatedTable/PaginatedTableWithLayout.tsx index d9c930f0b..e8b49ced0 100644 --- a/src/components/PaginatedTable/PaginatedTableWithLayout.tsx +++ b/src/components/PaginatedTable/PaginatedTableWithLayout.tsx @@ -9,7 +9,7 @@ import type {PaginatedTableState} from './types'; export interface PaginatedTableWithLayoutProps { controls?: React.ReactNode; table: React.ReactNode; - tableWrapperProps?: TableWrapperProps; + tableWrapperProps?: Omit; error?: React.ReactNode; initialState?: Partial; fullHeight?: boolean; @@ -21,7 +21,7 @@ const TableWrapper = ({ tableWrapperProps, }: { table: React.ReactNode; - tableWrapperProps?: TableWrapperProps; + tableWrapperProps?: Omit; }) => { const {tableState} = usePaginatedTableState(); const {sortParams} = tableState; diff --git a/src/components/ResizeableDataTable/ResizeableDataTable.tsx b/src/components/ResizeableDataTable/ResizeableDataTable.tsx index 186b18315..69793deb0 100644 --- a/src/components/ResizeableDataTable/ResizeableDataTable.tsx +++ b/src/components/ResizeableDataTable/ResizeableDataTable.tsx @@ -1,3 +1,5 @@ +import React from 'react'; + import type {Column, DataTableProps, Settings} from '@gravity-ui/react-data-table'; import DataTable, {updateColumnsWidth} from '@gravity-ui/react-data-table'; import {Skeleton} from '@gravity-ui/uikit'; @@ -13,6 +15,7 @@ export interface ResizeableDataTableProps extends Omit, 'th columnsWidthLSKey?: string; wrapperClassName?: string; loading?: boolean; + onSortChange?: (params: any) => void; } export function ResizeableDataTable({ @@ -21,10 +24,20 @@ export function ResizeableDataTable({ settings, wrapperClassName, loading, + onSort, + onSortChange, ...props }: ResizeableDataTableProps) { const [tableColumnsWidth, setTableColumnsWidth] = useTableResize(columnsWidthLSKey); + const handleSort = React.useCallback( + (params: any) => { + onSort?.(params); // Original onSort if provided + onSortChange?.(params); // Expose sort params to parent + }, + [onSort, onSortChange], + ); + // If loading is true, override the render method of each column to display a Skeleton const processedColumns = loading ? columns.map((column: Column) => ({ @@ -46,6 +59,7 @@ export function ResizeableDataTable({ theme="yandex-cloud" columns={updatedColumns} onResize={setTableColumnsWidth} + onSort={handleSort} settings={newSettings} {...props} /> diff --git a/src/components/TableWithControlsLayout/TableWithControlsLayout.tsx b/src/components/TableWithControlsLayout/TableWithControlsLayout.tsx index bc3cef0fd..cec3679ac 100644 --- a/src/components/TableWithControlsLayout/TableWithControlsLayout.tsx +++ b/src/components/TableWithControlsLayout/TableWithControlsLayout.tsx @@ -12,7 +12,7 @@ import './TableWithControlsLayout.scss'; const b = cn('ydb-table-with-controls-layout'); interface TableWithControlsLayoutItemProps { - children?: React.ReactNode; + children: React.ReactNode; renderExtraControls?: () => React.ReactNode; className?: string; fullHeight?: boolean; @@ -22,10 +22,7 @@ export interface TableWrapperProps extends Omit; scrollDependencies?: any[]; - - // onSort is called with the table's sort parameters and triggers auto-scrolling. - onSort?: (params: any) => void; - children?: React.ReactNode | ((props: {onSort: (params: any) => void}) => React.ReactNode); + children: React.ReactNode; } export const TableWithControlsLayout = ({ @@ -60,34 +57,24 @@ TableWithControlsLayout.Table = function Table({ className, scrollContainerRef, scrollDependencies = [], - onSort, }: TableWrapperProps) { // Create an internal ref for the table container const tableContainerRef = React.useRef(null); // Use the internal ref for scrolling - const {handleTableScroll} = useTableScroll({ + useTableScroll({ tableContainerRef, scrollContainerRef, dependencies: scrollDependencies, }); - // Create a wrapper function that triggers scroll on sort - const handleSort = React.useCallback( - (params: any) => { - onSort?.(params); // Call original callback if provided - handleTableScroll(); // Trigger scroll to top - }, - [onSort, handleTableScroll], - ); - if (loading) { return ; } return (
- {typeof children === 'function' ? children({onSort: handleSort}) : children} + {children}
); }; diff --git a/src/containers/Tablets/TabletsTable.tsx b/src/containers/Tablets/TabletsTable.tsx index d00a71594..f4b6b8503 100644 --- a/src/containers/Tablets/TabletsTable.tsx +++ b/src/containers/Tablets/TabletsTable.tsx @@ -183,6 +183,9 @@ export function TabletsTable({ tabletsSearch: StringParam, }); + // Track sort state for scroll dependencies + const [sortParams, setSortParams] = React.useState(); + const columns = React.useMemo(() => getColumns({database}), [database]); const filteredTablets = React.useMemo(() => { @@ -214,18 +217,16 @@ export function TabletsTable({ {error ? : null} - {({onSort}) => ( - - )} + ); diff --git a/src/containers/Tenants/Tenants.tsx b/src/containers/Tenants/Tenants.tsx index fd49ec01c..e6afe057a 100644 --- a/src/containers/Tenants/Tenants.tsx +++ b/src/containers/Tenants/Tenants.tsx @@ -70,6 +70,9 @@ export const Tenants = ({additionalTenantsProps, scrollContainerRef}: TenantsPro ); const loading = isFetching && currentData === undefined; + // Track sort state for scroll dependencies + const [sortParams, setSortParams] = React.useState(); + const isCreateDBAvailable = useCreateDatabaseFeatureAvailable() && uiFactory.onCreateDB !== undefined; const isEditDBAvailable = useEditDatabaseFeatureAvailable() && uiFactory.onEditDB !== undefined; @@ -128,7 +131,7 @@ export const Tenants = ({additionalTenantsProps, scrollContainerRef}: TenantsPro ); }; - const renderTable = (onSort?: (params: any) => void) => { + const renderTable = () => { const columns: Column[] = [ { name: 'Name', @@ -261,7 +264,7 @@ export const Tenants = ({additionalTenantsProps, scrollContainerRef}: TenantsPro columns={columns} settings={DEFAULT_TABLE_SETTINGS} emptyDataMessage="No such tenants" - onSort={onSort} + onSortChange={setSortParams} /> ); }; @@ -276,9 +279,9 @@ export const Tenants = ({additionalTenantsProps, scrollContainerRef}: TenantsPro - {({onSort}) => (currentData ? renderTable(onSort) : null)} + {currentData ? renderTable() : null} From e7ce2c98004a4d214f6cf14544a9922ecc221f1c Mon Sep 17 00:00:00 2001 From: astandrik Date: Tue, 3 Jun 2025 12:52:33 +0300 Subject: [PATCH 6/6] fix: types --- src/components/ResizeableDataTable/ResizeableDataTable.tsx | 6 +++--- src/containers/Tablets/TabletsTable.tsx | 4 ++-- src/containers/Tenants/Tenants.tsx | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/components/ResizeableDataTable/ResizeableDataTable.tsx b/src/components/ResizeableDataTable/ResizeableDataTable.tsx index 69793deb0..9eefb505d 100644 --- a/src/components/ResizeableDataTable/ResizeableDataTable.tsx +++ b/src/components/ResizeableDataTable/ResizeableDataTable.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import type {Column, DataTableProps, Settings} from '@gravity-ui/react-data-table'; +import type {Column, DataTableProps, Settings, SortOrder} from '@gravity-ui/react-data-table'; import DataTable, {updateColumnsWidth} from '@gravity-ui/react-data-table'; import {Skeleton} from '@gravity-ui/uikit'; @@ -15,7 +15,7 @@ export interface ResizeableDataTableProps extends Omit, 'th columnsWidthLSKey?: string; wrapperClassName?: string; loading?: boolean; - onSortChange?: (params: any) => void; + onSortChange?: (params: SortOrder | SortOrder[] | undefined) => void; } export function ResizeableDataTable({ @@ -31,7 +31,7 @@ export function ResizeableDataTable({ const [tableColumnsWidth, setTableColumnsWidth] = useTableResize(columnsWidthLSKey); const handleSort = React.useCallback( - (params: any) => { + (params: SortOrder | SortOrder[] | undefined) => { onSort?.(params); // Original onSort if provided onSortChange?.(params); // Expose sort params to parent }, diff --git a/src/containers/Tablets/TabletsTable.tsx b/src/containers/Tablets/TabletsTable.tsx index f4b6b8503..3cddfd5d9 100644 --- a/src/containers/Tablets/TabletsTable.tsx +++ b/src/containers/Tablets/TabletsTable.tsx @@ -1,7 +1,7 @@ import React from 'react'; import {ArrowRotateLeft} from '@gravity-ui/icons'; -import type {Column as DataTableColumn} from '@gravity-ui/react-data-table'; +import type {Column as DataTableColumn, SortOrder} from '@gravity-ui/react-data-table'; import {Icon, Text} from '@gravity-ui/uikit'; import {StringParam, useQueryParams} from 'use-query-params'; @@ -184,7 +184,7 @@ export function TabletsTable({ }); // Track sort state for scroll dependencies - const [sortParams, setSortParams] = React.useState(); + const [sortParams, setSortParams] = React.useState(); const columns = React.useMemo(() => getColumns({database}), [database]); diff --git a/src/containers/Tenants/Tenants.tsx b/src/containers/Tenants/Tenants.tsx index e6afe057a..e9e94e904 100644 --- a/src/containers/Tenants/Tenants.tsx +++ b/src/containers/Tenants/Tenants.tsx @@ -1,7 +1,7 @@ import React from 'react'; import {CirclePlus, Pencil, TrashBin} from '@gravity-ui/icons'; -import type {Column} from '@gravity-ui/react-data-table'; +import type {Column, SortOrder} from '@gravity-ui/react-data-table'; import DataTable from '@gravity-ui/react-data-table'; import type {DropdownMenuItem} from '@gravity-ui/uikit'; import {Button, DropdownMenu, Icon} from '@gravity-ui/uikit'; @@ -71,7 +71,7 @@ export const Tenants = ({additionalTenantsProps, scrollContainerRef}: TenantsPro const loading = isFetching && currentData === undefined; // Track sort state for scroll dependencies - const [sortParams, setSortParams] = React.useState(); + const [sortParams, setSortParams] = React.useState(); const isCreateDBAvailable = useCreateDatabaseFeatureAvailable() && uiFactory.onCreateDB !== undefined;