diff --git a/src/components/PaginatedTable/TableChunk.tsx b/src/components/PaginatedTable/TableChunk.tsx index b77f87353b..430b65b26b 100644 --- a/src/components/PaginatedTable/TableChunk.tsx +++ b/src/components/PaginatedTable/TableChunk.tsx @@ -104,8 +104,8 @@ export const TableChunk = typedMemo(function TableChunk({ }, [currentData, isActive, onDataFetched]); const chunkOffset = id * limit; - const remainingLenght = totalLength - chunkOffset; - const calculatedChunkLength = remainingLenght < limit ? remainingLenght : limit; + const remainingLength = totalLength - chunkOffset; + const calculatedChunkLength = remainingLength < limit ? remainingLength : limit; const dataLength = currentData?.data?.length || calculatedChunkLength; diff --git a/src/containers/PDiskPage/PDiskPage.tsx b/src/containers/PDiskPage/PDiskPage.tsx index b2e4b7b86d..d07035b0d5 100644 --- a/src/containers/PDiskPage/PDiskPage.tsx +++ b/src/containers/PDiskPage/PDiskPage.tsx @@ -25,7 +25,7 @@ import {valueIsDefined} from '../../utils'; import {cn} from '../../utils/cn'; import {getPDiskId, getSeverityColor} from '../../utils/disks/helpers'; import {useAutoRefreshInterval, useTypedDispatch, useTypedSelector} from '../../utils/hooks'; -import {Storage} from '../Storage/Storage'; +import {StorageWrapper} from '../Storage/StorageWrapper'; import {DecommissionButton} from './DecommissionButton/DecommissionButton'; import {DecommissionLabel} from './DecommissionLabel/DecommissionLabel'; @@ -244,7 +244,9 @@ export function PDiskPage() { ) : null; } case 'storage': { - return pDiskParamsDefined ? : null; + return pDiskParamsDefined ? ( + + ) : null; } default: return null; diff --git a/src/containers/Storage/Disks/Disks.tsx b/src/containers/Storage/Disks/Disks.tsx index 0994f24881..3a1f67db76 100644 --- a/src/containers/Storage/Disks/Disks.tsx +++ b/src/containers/Storage/Disks/Disks.tsx @@ -6,8 +6,8 @@ import {stringifyVdiskId} from '../../../utils/dataFormatters/dataFormatters'; import {getPDiskId} from '../../../utils/disks/helpers'; import type {PreparedVDisk} from '../../../utils/disks/types'; import {PDisk} from '../PDisk'; +import type {StorageViewContext} from '../types'; import {isVdiskActive} from '../utils'; -import type {VDiskViewContext} from '../utils'; import './Disks.scss'; @@ -15,7 +15,7 @@ const b = cn('ydb-storage-disks'); interface DisksProps { vDisks?: PreparedVDisk[]; - viewContext?: VDiskViewContext; + viewContext?: StorageViewContext; } export function Disks({vDisks = [], viewContext}: DisksProps) { diff --git a/src/containers/Storage/PDisk/PDisk.tsx b/src/containers/Storage/PDisk/PDisk.tsx index 43150e261f..e71d669ad6 100644 --- a/src/containers/Storage/PDisk/PDisk.tsx +++ b/src/containers/Storage/PDisk/PDisk.tsx @@ -11,8 +11,8 @@ import {cn} from '../../../utils/cn'; import {stringifyVdiskId} from '../../../utils/dataFormatters/dataFormatters'; import type {PreparedPDisk, PreparedVDisk} from '../../../utils/disks/types'; import {STRUCTURE} from '../../Node/NodePages'; +import type {StorageViewContext} from '../types'; import {isVdiskActive} from '../utils'; -import type {VDiskViewContext} from '../utils'; import './PDisk.scss'; @@ -26,7 +26,7 @@ interface PDiskProps { onHidePopup?: VoidFunction; className?: string; progressBarClassName?: string; - viewContext?: VDiskViewContext; + viewContext?: StorageViewContext; } export const PDisk = ({ diff --git a/src/containers/Storage/PaginatedStorage.tsx b/src/containers/Storage/PaginatedStorage.tsx index 804a5714d5..fbed03f345 100644 --- a/src/containers/Storage/PaginatedStorage.tsx +++ b/src/containers/Storage/PaginatedStorage.tsx @@ -1,6 +1,8 @@ import {PaginatedStorageGroups} from './PaginatedStorageGroups'; import {PaginatedStorageNodes} from './PaginatedStorageNodes'; +import type {StorageViewContext} from './types'; import {useStorageQueryParams} from './useStorageQueryParams'; +import {getStorageGroupsInitialEntitiesCount, getStorageNodesInitialEntitiesCount} from './utils'; export interface PaginatedStorageProps { database?: string; @@ -8,7 +10,11 @@ export interface PaginatedStorageProps { groupId?: string | number; pDiskId?: string | number; + viewContext: StorageViewContext; + parentContainer?: Element | null; + + initialEntitiesCount?: number; } export const PaginatedStorage = (props: PaginatedStorageProps) => { @@ -17,8 +23,18 @@ export const PaginatedStorage = (props: PaginatedStorageProps) => { const isNodes = storageType === 'nodes'; if (isNodes) { - return ; + return ( + + ); } - return ; + return ( + + ); }; diff --git a/src/containers/Storage/PaginatedStorageGroups.tsx b/src/containers/Storage/PaginatedStorageGroups.tsx index d20f0e650b..f4b2b0b82e 100644 --- a/src/containers/Storage/PaginatedStorageGroups.tsx +++ b/src/containers/Storage/PaginatedStorageGroups.tsx @@ -54,13 +54,15 @@ function StorageGroupsComponent({ nodeId, groupId, pDiskId, + viewContext, parentContainer, + initialEntitiesCount, }: PaginatedStorageProps) { const {searchValue, visibleEntities, handleShowAllGroups} = useStorageQueryParams(); const {columnsToShow, columnsToSelect, setColumns} = useStorageGroupsSelectedColumns({ visibleEntities, - nodeId: nodeId?.toString(), + viewContext, }); const renderControls: RenderControls = ({totalEntities, foundEntities, inited}) => { @@ -90,6 +92,7 @@ function StorageGroupsComponent({ renderControls={renderControls} renderErrorMessage={renderPaginatedTableErrorMessage} columns={columnsToShow} + initialEntitiesCount={initialEntitiesCount} /> ); } @@ -99,6 +102,8 @@ function GroupedStorageGroupsComponent({ nodeId, groupId, pDiskId, + + viewContext, }: PaginatedStorageProps) { const [autoRefreshInterval] = useAutoRefreshInterval(); const {searchValue, storageGroupsGroupByParam, visibleEntities, handleShowAllGroups} = @@ -106,7 +111,7 @@ function GroupedStorageGroupsComponent({ const {columnsToShow, columnsToSelect, setColumns} = useStorageGroupsSelectedColumns({ visibleEntities, - nodeId: nodeId?.toString(), + viewContext, }); const {currentData, isFetching, error} = storageApi.useGetStorageGroupsInfoQuery( diff --git a/src/containers/Storage/PaginatedStorageNodes.tsx b/src/containers/Storage/PaginatedStorageNodes.tsx index cf237c1d8e..e82fb4366f 100644 --- a/src/containers/Storage/PaginatedStorageNodes.tsx +++ b/src/containers/Storage/PaginatedStorageNodes.tsx @@ -22,6 +22,7 @@ import {TableGroup} from './TableGroup/TableGroup'; import {useExpandedGroups} from './TableGroup/useExpandedTableGroups'; import i18n from './i18n'; import {b, renderPaginatedTableErrorMessage} from './shared'; +import type {StorageViewContext} from './types'; import {useStorageQueryParams} from './useStorageQueryParams'; import './Storage.scss'; @@ -60,14 +61,16 @@ function StorageNodesComponent({ database, nodeId, groupId, + viewContext, parentContainer, + initialEntitiesCount, }: PaginatedStorageProps) { const {searchValue, visibleEntities, nodesUptimeFilter, handleShowAllNodes} = useStorageQueryParams(); const {columnsToShow, columnsToSelect, setColumns} = useStorageNodesColumnsToSelect({ database, - groupId: groupId?.toString(), + viewContext, }); const renderControls: RenderControls = ({totalEntities, foundEntities, inited}) => { @@ -97,18 +100,24 @@ function StorageNodesComponent({ renderControls={renderControls} renderErrorMessage={renderPaginatedTableErrorMessage} columns={columnsToShow} + initialEntitiesCount={initialEntitiesCount} /> ); } -function GroupedStorageNodesComponent({database, groupId, nodeId}: PaginatedStorageProps) { +function GroupedStorageNodesComponent({ + database, + groupId, + nodeId, + viewContext, +}: PaginatedStorageProps) { const [autoRefreshInterval] = useAutoRefreshInterval(); const {searchValue, storageNodesGroupByParam, handleShowAllNodes} = useStorageQueryParams(); const {columnsToShow, columnsToSelect, setColumns} = useStorageNodesColumnsToSelect({ database, - groupId: groupId?.toString(), + viewContext, }); const {currentData, isFetching, error} = storageApi.useGetStorageNodesInfoQuery( @@ -193,10 +202,10 @@ function GroupedStorageNodesComponent({database, groupId, nodeId}: PaginatedStor function useStorageNodesColumnsToSelect({ database, - groupId, + viewContext, }: { database?: string; - groupId?: string; + viewContext: StorageViewContext; }) { const {balancer} = useClusterBaseInfo(); const {additionalNodesProps} = useAdditionalNodeProps({balancer}); @@ -206,6 +215,6 @@ function useStorageNodesColumnsToSelect({ additionalNodesProps, visibleEntities, database, - groupId, + viewContext, }); } diff --git a/src/containers/Storage/Storage.tsx b/src/containers/Storage/Storage.tsx index 7d7ce86ea3..19dc9d8751 100644 --- a/src/containers/Storage/Storage.tsx +++ b/src/containers/Storage/Storage.tsx @@ -22,6 +22,7 @@ import {useStorageGroupsSelectedColumns} from './StorageGroups/columns/hooks'; import {StorageNodesTable} from './StorageNodes/StorageNodesTable'; import {useStorageNodesSelectedColumns} from './StorageNodes/columns/hooks'; import {b} from './shared'; +import type {StorageViewContext} from './types'; import {useStorageQueryParams} from './useStorageQueryParams'; import {defaultSortNode, getDefaultSortGroup} from './utils'; @@ -32,9 +33,11 @@ interface StorageProps { nodeId?: string | number; groupId?: string | number; pDiskId?: string | number; + + viewContext: StorageViewContext; } -export const Storage = ({database, nodeId, groupId, pDiskId}: StorageProps) => { +export const Storage = ({database, viewContext, nodeId, groupId, pDiskId}: StorageProps) => { const {balancer} = useClusterBaseInfo(); const {additionalNodesProps} = useAdditionalNodeProps({balancer}); @@ -75,14 +78,14 @@ export const Storage = ({database, nodeId, groupId, pDiskId}: StorageProps) => { additionalNodesProps, visibleEntities, database, - groupId: groupId?.toString(), + viewContext, }); const { columnsToShow: storageGroupsColumnsToShow, columnsToSelect: storageGroupsColumnsToSelect, setColumns: setStorageGroupsSelectedColumns, - } = useStorageGroupsSelectedColumns({visibleEntities, nodeId: nodeId?.toString()}); + } = useStorageGroupsSelectedColumns({visibleEntities, viewContext}); const nodesQuery = storageApi.useGetStorageNodesInfoQuery( { diff --git a/src/containers/Storage/StorageGroups/columns/columns.tsx b/src/containers/Storage/StorageGroups/columns/columns.tsx index e467c2e414..636bffb5bb 100644 --- a/src/containers/Storage/StorageGroups/columns/columns.tsx +++ b/src/containers/Storage/StorageGroups/columns/columns.tsx @@ -220,7 +220,7 @@ const getVDisksColumn = (data?: GetStorageColumnsData): StorageGroupsColumn => ( ))} @@ -237,7 +237,7 @@ const getDisksColumn = (data?: GetStorageColumnsData): StorageGroupsColumn => ({ header: STORAGE_GROUPS_COLUMNS_TITLES.VDisksPDisks, className: b('disks-column'), render: ({row}) => { - return ; + return ; }, align: DataTable.CENTER, width: 900, diff --git a/src/containers/Storage/StorageGroups/columns/hooks.ts b/src/containers/Storage/StorageGroups/columns/hooks.ts index d58d716bad..bb0948a07f 100644 --- a/src/containers/Storage/StorageGroups/columns/hooks.ts +++ b/src/containers/Storage/StorageGroups/columns/hooks.ts @@ -2,6 +2,7 @@ import React from 'react'; import {VISIBLE_ENTITIES} from '../../../../store/reducers/storage/constants'; import {useSelectedColumns} from '../../../../utils/hooks/useSelectedColumns'; +import type {StorageViewContext} from '../../types'; import {getStorageGroupsColumns} from './columns'; import { @@ -13,17 +14,17 @@ import { } from './constants'; import type {GetStorageGroupsColumnsParams} from './types'; -export function useGetStorageGroupsColumns(nodeId?: string) { +export function useGetStorageGroupsColumns(viewContext: StorageViewContext) { return React.useMemo(() => { - return getStorageGroupsColumns({nodeId}); - }, [nodeId]); + return getStorageGroupsColumns({viewContext}); + }, [viewContext]); } export function useStorageGroupsSelectedColumns({ visibleEntities, - nodeId, + viewContext, }: GetStorageGroupsColumnsParams) { - const columns = useGetStorageGroupsColumns(nodeId); + const columns = useGetStorageGroupsColumns(viewContext); const requiredColumns = React.useMemo(() => { if (visibleEntities === VISIBLE_ENTITIES.missing) { diff --git a/src/containers/Storage/StorageGroups/columns/types.ts b/src/containers/Storage/StorageGroups/columns/types.ts index dccb9affaa..8697d44232 100644 --- a/src/containers/Storage/StorageGroups/columns/types.ts +++ b/src/containers/Storage/StorageGroups/columns/types.ts @@ -2,17 +2,18 @@ import type {Column as DataTableColumn} from '@gravity-ui/react-data-table'; import type {Column as PaginatedTableColumn} from '../../../../components/PaginatedTable'; import type {PreparedStorageGroup, VisibleEntities} from '../../../../store/reducers/storage/types'; +import type {StorageViewContext} from '../../types'; export type StorageGroupsColumn = PaginatedTableColumn & DataTableColumn; export interface GetStorageColumnsData { - nodeId?: string; + viewContext: StorageViewContext; } export interface GetStorageGroupsColumnsParams { visibleEntities?: VisibleEntities; - nodeId?: string; + viewContext: StorageViewContext; } export type StorageColumnsGetter = (data?: GetStorageColumnsData) => StorageGroupsColumn[]; diff --git a/src/containers/Storage/StorageNodes/columns/columns.tsx b/src/containers/Storage/StorageNodes/columns/columns.tsx index 303b89e070..8c41f0bb54 100644 --- a/src/containers/Storage/StorageNodes/columns/columns.tsx +++ b/src/containers/Storage/StorageNodes/columns/columns.tsx @@ -16,7 +16,7 @@ const b = cn('ydb-storage-nodes-columns'); const getStorageNodesColumns = ({ additionalNodesProps, database, - groupId, + viewContext, }: GetStorageNodesColumnsParams) => { const getNodeRef = additionalNodesProps?.getNodeRef; @@ -81,7 +81,7 @@ const getStorageNodesColumns = ({ return (
- +
); })} diff --git a/src/containers/Storage/StorageNodes/columns/hooks.ts b/src/containers/Storage/StorageNodes/columns/hooks.ts index 0e09430461..1dc8415b71 100644 --- a/src/containers/Storage/StorageNodes/columns/hooks.ts +++ b/src/containers/Storage/StorageNodes/columns/hooks.ts @@ -17,11 +17,15 @@ export function useStorageNodesSelectedColumns({ visibleEntities, database, additionalNodesProps, - groupId, + viewContext, }: GetStorageNodesColumnsParams) { const columns = React.useMemo(() => { - return getPreparedStorageNodesColumns({database, additionalNodesProps, groupId}); - }, [database, additionalNodesProps, groupId]); + return getPreparedStorageNodesColumns({ + database, + additionalNodesProps, + viewContext, + }); + }, [database, additionalNodesProps, viewContext]); const requiredColumns = React.useMemo(() => { if (visibleEntities === VISIBLE_ENTITIES.missing) { diff --git a/src/containers/Storage/StorageNodes/columns/types.ts b/src/containers/Storage/StorageNodes/columns/types.ts index 5db463c2c3..14f0bbe1d0 100644 --- a/src/containers/Storage/StorageNodes/columns/types.ts +++ b/src/containers/Storage/StorageNodes/columns/types.ts @@ -3,6 +3,7 @@ import type {Column as DataTableColumn} from '@gravity-ui/react-data-table'; import type {Column as PaginatedTableColumn} from '../../../../components/PaginatedTable'; import type {PreparedStorageNode, VisibleEntities} from '../../../../store/reducers/storage/types'; import type {AdditionalNodesProps} from '../../../../types/additionalProps'; +import type {StorageViewContext} from '../../types'; export type StorageNodesColumn = PaginatedTableColumn & DataTableColumn; @@ -11,5 +12,5 @@ export interface GetStorageNodesColumnsParams { additionalNodesProps: AdditionalNodesProps | undefined; visibleEntities?: VisibleEntities; database?: string; - groupId?: string; + viewContext: StorageViewContext; } diff --git a/src/containers/Storage/StorageWrapper.tsx b/src/containers/Storage/StorageWrapper.tsx index d2c64aa32b..ce4b6bcd50 100644 --- a/src/containers/Storage/StorageWrapper.tsx +++ b/src/containers/Storage/StorageWrapper.tsx @@ -3,19 +3,36 @@ import {useSetting} from '../../utils/hooks'; import {PaginatedStorage} from './PaginatedStorage'; import {Storage} from './Storage'; +import type {StorageViewContext} from './types'; interface StorageWrapperProps { database?: string; - nodeId?: string; + nodeId?: string | number; + pDiskId?: string | number; + groupId?: string | number; + vDiskSlotId?: string | number; parentContainer?: Element | null; } export const StorageWrapper = ({parentContainer, ...props}: StorageWrapperProps) => { const [usePaginatedTables] = useSetting(USE_PAGINATED_TABLES_KEY); + const viewContext: StorageViewContext = { + nodeId: props.nodeId?.toString(), + pDiskId: props.pDiskId?.toString(), + groupId: props.groupId?.toString(), + vDiskSlotId: props.vDiskSlotId?.toString(), + }; + if (usePaginatedTables) { - return ; + return ( + + ); } - return ; + return ; }; diff --git a/src/containers/Storage/types.ts b/src/containers/Storage/types.ts new file mode 100644 index 0000000000..9e9942c406 --- /dev/null +++ b/src/containers/Storage/types.ts @@ -0,0 +1,6 @@ +export type StorageViewContext = { + groupId?: string; + nodeId?: string; + pDiskId?: string; + vDiskSlotId?: string; +}; diff --git a/src/containers/Storage/utils/index.ts b/src/containers/Storage/utils/index.ts index a8dad2d3f3..5105d0a82e 100644 --- a/src/containers/Storage/utils/index.ts +++ b/src/containers/Storage/utils/index.ts @@ -12,6 +12,7 @@ import type {PreparedVDisk} from '../../../utils/disks/types'; import {generateEvaluator} from '../../../utils/generateEvaluator'; import {NODES_COLUMNS_IDS} from '../../Nodes/columns/constants'; import {STORAGE_GROUPS_COLUMNS_IDS} from '../StorageGroups/columns/constants'; +import type {StorageViewContext} from '../types'; const defaultDegradationEvaluator = generateEvaluator(1, 2, ['success', 'warning', 'danger']); @@ -67,19 +68,59 @@ export function getDefaultSortGroup(visibleEntities: VisibleEntities) { return defaultSortGroup; } -export type VDiskViewContext = { - groupId?: string; - nodeId?: string; -}; - -export function isVdiskActive(vDisk: PreparedVDisk, viewContext?: VDiskViewContext) { +export function isVdiskActive(vDisk: PreparedVDisk, viewContext?: StorageViewContext) { + let isActive = true; if (valueIsDefined(vDisk.VDiskId?.GroupID) && viewContext?.groupId) { - return String(vDisk.VDiskId.GroupID) === viewContext.groupId; + isActive &&= String(vDisk.VDiskId.GroupID) === viewContext.groupId; } if (valueIsDefined(vDisk.NodeId) && viewContext?.nodeId) { - return String(vDisk.NodeId) === viewContext.nodeId; + isActive &&= String(vDisk.NodeId) === viewContext.nodeId; + } + + if (valueIsDefined(vDisk.PDiskId) && viewContext?.pDiskId) { + isActive &&= String(vDisk.PDiskId) === viewContext.pDiskId; + } + + if (valueIsDefined(vDisk.VDiskSlotId) && viewContext?.vDiskSlotId) { + isActive &&= String(vDisk.VDiskSlotId) === viewContext.vDiskSlotId; + } + + return isActive; +} + +const DEFAULT_ENTITIES_COUNT = 10; + +// NodePage - 1 node +// GroupPage - DEFAULT_ENTITIES_COUNT nodes +// PDiskPage - 1 node +// VDiskPage - 1 node +export function getStorageNodesInitialEntitiesCount({ + nodeId, + pDiskId, + vDiskSlotId, +}: StorageViewContext): number | undefined { + if (valueIsDefined(nodeId) || valueIsDefined(pDiskId) || valueIsDefined(vDiskSlotId)) { + return 1; + } + + return DEFAULT_ENTITIES_COUNT; +} + +// NodePage - DEFAULT_ENTITIES_COUNT groups +// GroupPage - 1 group +// PDiskPage - DEFAULT_ENTITIES_COUNT groups +// VDiskPage - 1 group +export function getStorageGroupsInitialEntitiesCount({ + vDiskSlotId, + groupId, +}: StorageViewContext): number | undefined { + if (valueIsDefined(groupId)) { + return 1; + } + if (valueIsDefined(vDiskSlotId)) { + return 1; } - return true; + return DEFAULT_ENTITIES_COUNT; } diff --git a/src/containers/StorageGroupPage/StorageGroupPage.tsx b/src/containers/StorageGroupPage/StorageGroupPage.tsx index 14ff38806e..fe4c6e530b 100644 --- a/src/containers/StorageGroupPage/StorageGroupPage.tsx +++ b/src/containers/StorageGroupPage/StorageGroupPage.tsx @@ -19,7 +19,7 @@ import {EFlag} from '../../types/api/enums'; import {valueIsDefined} from '../../utils'; import {cn} from '../../utils/cn'; import {useAutoRefreshInterval, useTypedDispatch} from '../../utils/hooks'; -import {Storage} from '../Storage/Storage'; +import {StorageWrapper} from '../Storage/StorageWrapper'; import {storageGroupPageKeyset} from './i18n'; @@ -107,7 +107,7 @@ export function StorageGroupPage() {
{storageGroupPageKeyset('storage')}
- + ); }; diff --git a/src/containers/VDiskPage/VDiskPage.tsx b/src/containers/VDiskPage/VDiskPage.tsx index 5c87a038b2..30846b05dc 100644 --- a/src/containers/VDiskPage/VDiskPage.tsx +++ b/src/containers/VDiskPage/VDiskPage.tsx @@ -22,7 +22,7 @@ import {cn} from '../../utils/cn'; import {stringifyVdiskId} from '../../utils/dataFormatters/dataFormatters'; import {getSeverityColor, getVDiskSlotBasedId} from '../../utils/disks/helpers'; import {useAutoRefreshInterval, useTypedDispatch, useTypedSelector} from '../../utils/hooks'; -import {Storage} from '../Storage/Storage'; +import {StorageWrapper} from '../Storage/StorageWrapper'; import {vDiskPageKeyset} from './i18n'; @@ -178,7 +178,12 @@ export function VDiskPage() { return (
{vDiskPageKeyset('storage')}
- +
); }