diff --git a/src/containers/Cluster/Cluster.tsx b/src/containers/Cluster/Cluster.tsx index 81105958f0..57c83cd97e 100644 --- a/src/containers/Cluster/Cluster.tsx +++ b/src/containers/Cluster/Cluster.tsx @@ -26,7 +26,7 @@ import type { import {cn} from '../../utils/cn'; import {useTypedDispatch, useTypedSelector} from '../../utils/hooks'; import {parseVersionsToVersionToColorMap} from '../../utils/versions'; -import {NodesWrapper} from '../Nodes/NodesWrapper'; +import {Nodes} from '../Nodes/Nodes'; import {StorageWrapper} from '../Storage/StorageWrapper'; import {TabletsTable} from '../Tablets/TabletsTable'; import {Tenants} from '../Tenants/Tenants'; @@ -192,10 +192,7 @@ export function Cluster({ - + ; additionalNodesProps?: AdditionalNodesProps; + + columns?: Column[]; + defaultColumnsIds?: NodesColumnId[]; + requiredColumnsIds?: NodesColumnId[]; + selectedColumnsKey?: string; + groupByParams?: NodesGroupByField[]; } -export const Nodes = ({path, database, additionalNodesProps = {}}: NodesProps) => { - const {searchValue, uptimeFilter} = useNodesPageQueryParams(undefined); - const {problemFilter} = useProblemFilter(); +export function Nodes({ + path, + database, + parentRef, + additionalNodesProps, + columns = getNodesColumns({database, getNodeRef: additionalNodesProps?.getNodeRef}), + defaultColumnsIds = DEFAULT_NODES_COLUMNS, + requiredColumnsIds = REQUIRED_NODES_COLUMNS, + selectedColumnsKey = NODES_TABLE_SELECTED_COLUMNS_LS_KEY, + groupByParams = ALL_NODES_GROUP_BY_PARAMS, +}: NodesProps) { + const {uptimeFilter, groupByParam, handleUptimeFilterChange} = + useNodesPageQueryParams(groupByParams); + const {problemFilter, handleProblemFilterChange} = useProblemFilter(); - const [autoRefreshInterval] = useAutoRefreshInterval(); + const capabilitiesLoaded = useCapabilitiesLoaded(); + const viewerNodesHandlerHasGrouping = useViewerNodesHandlerHasGrouping(); - const {columnsToShow, columnsToSelect, setColumns} = useNodesSelectedColumns({ - getNodeRef: additionalNodesProps.getNodeRef, - database, - }); + // Other filters do not fit with grouping + // Reset them if grouping available + React.useEffect(() => { + if ( + viewerNodesHandlerHasGrouping && + (problemFilter !== 'All' || uptimeFilter !== NodesUptimeFilterValues.All) + ) { + handleProblemFilterChange('All'); + handleUptimeFilterChange(NodesUptimeFilterValues.All); + } + }, [ + handleProblemFilterChange, + handleUptimeFilterChange, + problemFilter, + uptimeFilter, + viewerNodesHandlerHasGrouping, + ]); - const { - currentData: data, - isLoading, - error, - } = nodesApi.useGetNodesQuery({path, database}, {pollingInterval: autoRefreshInterval}); + const renderContent = () => { + if (viewerNodesHandlerHasGrouping && groupByParam) { + return ( + + ); + } - const [sortValue, setSortValue] = React.useState({ - sortValue: 'NodeId', - sortOrder: ASCENDING, - }); - const [sort, handleSort] = useTableSort(sortValue, (sortParams) => { - setSortValue(sortParams as NodesSortParams); - }); + return ( + + ); + }; - const nodes = React.useMemo(() => { - return filterNodes(data?.Nodes, {searchValue, uptimeFilter, problemFilter}); - }, [data, searchValue, uptimeFilter, problemFilter]); + return {renderContent()}; +} - const totalNodes = data?.TotalNodes || 0; +interface NodesComponentProps { + path?: string; + database?: string; + parentRef: React.RefObject; - const renderControls = () => { + columns: Column[]; + defaultColumnsIds: NodesColumnId[]; + requiredColumnsIds: NodesColumnId[]; + selectedColumnsKey: string; + groupByParams: NodesGroupByField[]; +} + +function NodesComponent({ + path, + database, + parentRef, + columns, + defaultColumnsIds, + requiredColumnsIds, + selectedColumnsKey, + groupByParams, +}: NodesComponentProps) { + const {searchValue, uptimeFilter} = useNodesPageQueryParams(groupByParams); + const {problemFilter} = useProblemFilter(); + const viewerNodesHandlerHasGrouping = useViewerNodesHandlerHasGrouping(); + + const {columnsToShow, columnsToSelect, setColumns} = useSelectedColumns( + columns, + selectedColumnsKey, + NODES_COLUMNS_TITLES, + defaultColumnsIds, + requiredColumnsIds, + ); + + const renderControls: RenderControls = ({totalEntities, foundEntities, inited}) => { return ( ); }; - const renderTable = () => { - if (nodes.length === 0) { - if (problemFilter !== 'All' || uptimeFilter !== NodesUptimeFilterValues.All) { - return ; - } - } + return ( + + ); +} + +function GroupedNodesComponent({ + path, + database, + parentRef, + columns, + defaultColumnsIds, + requiredColumnsIds, + selectedColumnsKey, + groupByParams, +}: NodesComponentProps) { + const {searchValue, groupByParam} = useNodesPageQueryParams(groupByParams); + const [autoRefreshInterval] = useAutoRefreshInterval(); + + const {columnsToShow, columnsToSelect, setColumns} = useSelectedColumns( + columns, + selectedColumnsKey, + NODES_COLUMNS_TITLES, + defaultColumnsIds, + requiredColumnsIds, + ); + + const {currentData, isFetching, error} = nodesApi.useGetNodesQuery( + { + path, + database, + filter: searchValue, + group: groupByParam, + limit: 0, + }, + { + pollingInterval: autoRefreshInterval, + }, + ); + + const isLoading = currentData === undefined && isFetching; + const { + NodeGroups: tableGroups, + FoundNodes: found = 0, + TotalNodes: total = 0, + } = currentData || {}; + const {expandedGroups, setIsGroupExpanded} = useExpandedGroups(tableGroups); + + const renderControls = () => { return ( - ); }; - if (isAccessError(error)) { - return ; - } + const renderGroups = () => { + if (tableGroups?.length) { + return tableGroups.map(({name, count}) => { + const isExpanded = expandedGroups[name]; + + return ( + + + + ); + }); + } + + return i18n('no-nodes-groups'); + }; return ( {renderControls()} {error ? : null} - - {data ? renderTable() : null} + + {renderGroups()} ); -}; +} diff --git a/src/containers/Nodes/PaginatedNodesTable.tsx b/src/containers/Nodes/NodesTable.tsx similarity index 95% rename from src/containers/Nodes/PaginatedNodesTable.tsx rename to src/containers/Nodes/NodesTable.tsx index 91a27b301e..a2a0a50262 100644 --- a/src/containers/Nodes/PaginatedNodesTable.tsx +++ b/src/containers/Nodes/NodesTable.tsx @@ -14,7 +14,7 @@ import {getNodes} from './getNodes'; import i18n from './i18n'; import {getRowClassName, renderPaginatedTableErrorMessage} from './shared'; -interface PaginatedNodesTableProps { +interface NodesTableProps { path?: string; database?: string; @@ -32,7 +32,7 @@ interface PaginatedNodesTableProps { initialEntitiesCount?: number; } -export function PaginatedNodesTable({ +export function NodesTable({ path, database, searchValue, @@ -44,7 +44,7 @@ export function PaginatedNodesTable({ parentRef, renderControls, initialEntitiesCount, -}: PaginatedNodesTableProps) { +}: NodesTableProps) { const tableFilters = React.useMemo(() => { return { path, diff --git a/src/containers/Nodes/NodesWrapper.tsx b/src/containers/Nodes/NodesWrapper.tsx deleted file mode 100644 index aef41e2653..0000000000 --- a/src/containers/Nodes/NodesWrapper.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import type {AdditionalNodesProps} from '../../types/additionalProps'; -import {USE_PAGINATED_TABLES_KEY} from '../../utils/constants'; -import {useSetting} from '../../utils/hooks'; - -import {Nodes} from './Nodes'; -import {PaginatedNodes} from './PaginatedNodes'; - -interface NodesWrapperProps { - path?: string; - database?: string; - parentRef: React.RefObject; - additionalNodesProps?: AdditionalNodesProps; -} - -export const NodesWrapper = ({parentRef, ...props}: NodesWrapperProps) => { - const [usePaginatedTables] = useSetting(USE_PAGINATED_TABLES_KEY); - - if (usePaginatedTables) { - return ; - } - - return ; -}; diff --git a/src/containers/Nodes/PaginatedNodes.tsx b/src/containers/Nodes/PaginatedNodes.tsx deleted file mode 100644 index 5a3f74c98f..0000000000 --- a/src/containers/Nodes/PaginatedNodes.tsx +++ /dev/null @@ -1,283 +0,0 @@ -import React from 'react'; - -import {ResponseError} from '../../components/Errors/ResponseError'; -import {LoaderWrapper} from '../../components/LoaderWrapper/LoaderWrapper'; -import type {Column, RenderControls} from '../../components/PaginatedTable'; -import {TableWithControlsLayout} from '../../components/TableWithControlsLayout/TableWithControlsLayout'; -import {NODES_COLUMNS_TITLES} from '../../components/nodesColumns/constants'; -import type {NodesColumnId} from '../../components/nodesColumns/constants'; -import { - useCapabilitiesLoaded, - useViewerNodesHandlerHasGrouping, -} from '../../store/reducers/capabilities/hooks'; -import {nodesApi} from '../../store/reducers/nodes/nodes'; -import type {NodesPreparedEntity} from '../../store/reducers/nodes/types'; -import {useProblemFilter} from '../../store/reducers/settings/hooks'; -import type {AdditionalNodesProps} from '../../types/additionalProps'; -import type {NodesGroupByField} from '../../types/api/nodes'; -import {useAutoRefreshInterval} from '../../utils/hooks'; -import {useSelectedColumns} from '../../utils/hooks/useSelectedColumns'; -import {NodesUptimeFilterValues} from '../../utils/nodes'; -import {TableGroup} from '../Storage/TableGroup/TableGroup'; -import {useExpandedGroups} from '../Storage/TableGroup/useExpandedTableGroups'; - -import {NodesControls} from './NodesControls/NodesControls'; -import {PaginatedNodesTable} from './PaginatedNodesTable'; -import {getNodesColumns} from './columns/columns'; -import { - ALL_NODES_GROUP_BY_PARAMS, - DEFAULT_NODES_COLUMNS, - NODES_TABLE_SELECTED_COLUMNS_LS_KEY, - REQUIRED_NODES_COLUMNS, -} from './columns/constants'; -import i18n from './i18n'; -import {b} from './shared'; -import {useNodesPageQueryParams} from './useNodesPageQueryParams'; - -import './Nodes.scss'; - -export interface PaginatedNodesProps { - path?: string; - database?: string; - parentRef: React.RefObject; - additionalNodesProps?: AdditionalNodesProps; - - columns?: Column[]; - defaultColumnsIds?: NodesColumnId[]; - requiredColumnsIds?: NodesColumnId[]; - selectedColumnsKey?: string; - groupByParams?: NodesGroupByField[]; -} - -export function PaginatedNodes({ - path, - database, - parentRef, - additionalNodesProps, - columns = getNodesColumns({database, getNodeRef: additionalNodesProps?.getNodeRef}), - defaultColumnsIds = DEFAULT_NODES_COLUMNS, - requiredColumnsIds = REQUIRED_NODES_COLUMNS, - selectedColumnsKey = NODES_TABLE_SELECTED_COLUMNS_LS_KEY, - groupByParams = ALL_NODES_GROUP_BY_PARAMS, -}: PaginatedNodesProps) { - const {uptimeFilter, groupByParam, handleUptimeFilterChange} = - useNodesPageQueryParams(groupByParams); - const {problemFilter, handleProblemFilterChange} = useProblemFilter(); - - const capabilitiesLoaded = useCapabilitiesLoaded(); - const viewerNodesHandlerHasGrouping = useViewerNodesHandlerHasGrouping(); - - // Other filters do not fit with grouping - // Reset them if grouping available - React.useEffect(() => { - if ( - viewerNodesHandlerHasGrouping && - (problemFilter !== 'All' || uptimeFilter !== NodesUptimeFilterValues.All) - ) { - handleProblemFilterChange('All'); - handleUptimeFilterChange(NodesUptimeFilterValues.All); - } - }, [ - handleProblemFilterChange, - handleUptimeFilterChange, - problemFilter, - uptimeFilter, - viewerNodesHandlerHasGrouping, - ]); - - const renderContent = () => { - if (viewerNodesHandlerHasGrouping && groupByParam) { - return ( - - ); - } - - return ( - - ); - }; - - return {renderContent()}; -} - -interface PaginatedNodesComponentProps { - path?: string; - database?: string; - parentRef: React.RefObject; - - columns: Column[]; - defaultColumnsIds: NodesColumnId[]; - requiredColumnsIds: NodesColumnId[]; - selectedColumnsKey: string; - groupByParams: NodesGroupByField[]; -} - -function NodesComponent({ - path, - database, - parentRef, - columns, - defaultColumnsIds, - requiredColumnsIds, - selectedColumnsKey, - groupByParams, -}: PaginatedNodesComponentProps) { - const {searchValue, uptimeFilter} = useNodesPageQueryParams(groupByParams); - const {problemFilter} = useProblemFilter(); - const viewerNodesHandlerHasGrouping = useViewerNodesHandlerHasGrouping(); - - const {columnsToShow, columnsToSelect, setColumns} = useSelectedColumns( - columns, - selectedColumnsKey, - NODES_COLUMNS_TITLES, - defaultColumnsIds, - requiredColumnsIds, - ); - - const renderControls: RenderControls = ({totalEntities, foundEntities, inited}) => { - return ( - - ); - }; - - return ( - - ); -} - -function GroupedNodesComponent({ - path, - database, - parentRef, - columns, - defaultColumnsIds, - requiredColumnsIds, - selectedColumnsKey, - groupByParams, -}: PaginatedNodesComponentProps) { - const {searchValue, groupByParam} = useNodesPageQueryParams(groupByParams); - const [autoRefreshInterval] = useAutoRefreshInterval(); - - const {columnsToShow, columnsToSelect, setColumns} = useSelectedColumns( - columns, - selectedColumnsKey, - NODES_COLUMNS_TITLES, - defaultColumnsIds, - requiredColumnsIds, - ); - - const {currentData, isFetching, error} = nodesApi.useGetNodesQuery( - { - path, - database, - filter: searchValue, - group: groupByParam, - limit: 0, - }, - { - pollingInterval: autoRefreshInterval, - }, - ); - - const isLoading = currentData === undefined && isFetching; - const { - NodeGroups: tableGroups, - FoundNodes: found = 0, - TotalNodes: total = 0, - } = currentData || {}; - - const {expandedGroups, setIsGroupExpanded} = useExpandedGroups(tableGroups); - - const renderControls = () => { - return ( - - ); - }; - - const renderGroups = () => { - if (tableGroups?.length) { - return tableGroups.map(({name, count}) => { - const isExpanded = expandedGroups[name]; - - return ( - - - - ); - }); - } - - return i18n('no-nodes-groups'); - }; - - return ( - - {renderControls()} - {error ? : null} - - {renderGroups()} - - - ); -} diff --git a/src/containers/Tenant/Diagnostics/Diagnostics.tsx b/src/containers/Tenant/Diagnostics/Diagnostics.tsx index 6f54f674aa..75a32bb137 100644 --- a/src/containers/Tenant/Diagnostics/Diagnostics.tsx +++ b/src/containers/Tenant/Diagnostics/Diagnostics.tsx @@ -14,7 +14,7 @@ import type {EPathType} from '../../../types/api/schema'; import {cn} from '../../../utils/cn'; import {useTypedDispatch, useTypedSelector} from '../../../utils/hooks'; import {Heatmap} from '../../Heatmap'; -import {NodesWrapper} from '../../Nodes/NodesWrapper'; +import {Nodes} from '../../Nodes/Nodes'; import {Operations} from '../../Operations'; import {StorageWrapper} from '../../Storage/StorageWrapper'; import {Tablets} from '../../Tablets'; @@ -102,7 +102,7 @@ function Diagnostics(props: DiagnosticsProps) { } case TENANT_DIAGNOSTICS_TABS_IDS.nodes: { return ( - { + extends Pick { database: string; } @@ -37,7 +37,7 @@ export function NetworkWrapper({ const renderContent = () => { if (shouldUseNetworkNodesTable) { return ( - { const nodesPage = new NodesPage(page); const response = await nodesPage.goto(); expect(response?.ok()).toBe(true); - - // Wil be removed since it's an experiment - await toggleExperiment(page, 'on', 'Use paginated tables'); }); test('Table loads and displays data', async ({page}) => {