import React from 'react'; import {ResponseError} from '../../../components/Errors/ResponseError'; import {PaginatedTableWithLayout} from '../../../components/PaginatedTable/PaginatedTableWithLayout'; import {TableColumnSetup} from '../../../components/TableColumnSetup/TableColumnSetup'; import {NODES_COLUMNS_TO_DATA_FIELDS} from '../../../components/nodesColumns/constants'; import {storageApi} from '../../../store/reducers/storage/storage'; import type {NodesGroupByField, NodesRequiredField} from '../../../types/api/nodes'; import {useAutoRefreshInterval} from '../../../utils/hooks'; import {useHideUnavailableNodes} from '../../../utils/hooks/useHideUnavailableNodes'; import {NodesUptimeFilterValues} from '../../../utils/nodes'; import {renderPaginatedTableErrorMessage} from '../../../utils/renderPaginatedTableErrorMessage'; import {getRequiredDataFields} from '../../../utils/tableUtils/getRequiredDataFields'; import type {PaginatedStorageProps} from '../PaginatedStorage'; import {PaginatedStorageNodesTable} from '../PaginatedStorageNodesTable/PaginatedStorageNodesTable'; import {TableGroup} from '../TableGroup/TableGroup'; import {useExpandedGroups} from '../TableGroup/useExpandedTableGroups'; import i18n from '../i18n'; import {b} from '../shared'; import {useIsStorageExpertMode, useStorageQueryParams} from '../useStorageQueryParams'; import {useStorageColumnsSettings} from '../utils'; import {StorageNodesControls} from './StorageNodesControls'; import {useStorageNodesColumnsToSelect} from './useStorageNodesColumnsToSelect'; const NODE_SEARCH_FIELDS_REQUIRED = new Set(['Host', 'NodeName']); interface StorageNodeGroupProps { name: string; count: number; isExpanded: boolean; database?: string; nodeId?: string | number; groupId?: string | number; searchValue: string; visibleEntities: 'all'; filterGroupBy?: NodesGroupByField; columns: any[]; scrollContainerRef: React.RefObject; onIsExpandedChange: (name: string, isExpanded: boolean) => void; handleShowAllNodes: VoidFunction; onDataFetched: (data: any) => void; rowHeight: number; } export const StorageNodeGroup = React.memo(function StorageNodeGroup({ name, count, isExpanded, database, nodeId, groupId, searchValue, scrollContainerRef, filterGroupBy, columns, onIsExpandedChange, handleShowAllNodes, onDataFetched, rowHeight, }: StorageNodeGroupProps) { return ( } tableWrapperProps={{ scrollContainerRef: scrollContainerRef, }} /> ); }); export function GroupedStorageNodesComponent({ database, groupId, nodeId, viewContext, scrollContainerRef, }: PaginatedStorageProps) { const [autoRefreshInterval] = useAutoRefreshInterval(); const {hideUnavailable} = useHideUnavailableNodes(); const {nodesSearchValue, storageNodesGroupByParam, handleShowAllNodes} = useStorageQueryParams(); const expertMode = useIsStorageExpertMode(); const {handleDataFetched, columnsSettings, rowHeight} = useStorageColumnsSettings({ expertMode, }); const {columnsToShow, columnsToSelect, setColumns} = useStorageNodesColumnsToSelect({ database, viewContext, columnsSettings, }); const searchFieldsRequired = React.useMemo(() => { const activeFieldsRequired = getRequiredDataFields( columnsToShow.map(({name}) => name), NODES_COLUMNS_TO_DATA_FIELDS, ); return activeFieldsRequired.filter((field) => NODE_SEARCH_FIELDS_REQUIRED.has(field)); }, [columnsToShow]); const {currentData, isFetching, error} = storageApi.useGetStorageNodesInfoQuery( { database, alive: hideUnavailable || undefined, with: 'all', filter: nodesSearchValue.trim(), node_id: nodeId, group_id: groupId, group: storageNodesGroupByParam, fieldsRequired: nodesSearchValue.trim() ? searchFieldsRequired : undefined, }, { pollingInterval: autoRefreshInterval, }, ); const isLoading = currentData === undefined && isFetching; const {tableGroups, found = 0, total = 0} = currentData || {}; const {expandedGroups, setIsGroupExpanded} = useExpandedGroups(tableGroups); // Initialize the table state with the API data const initialState = React.useMemo( () => ({ foundEntities: found, totalEntities: total, isInitialLoad: isLoading, sortParams: undefined, }), [found, total, isLoading], ); const renderGroups = () => { if (tableGroups?.length) { return tableGroups.map(({name, count}) => { const isExpanded = expandedGroups[name]; return ( ); }); } return i18n('no-nodes'); }; return ( } extraControls={ } error={error ? : null} table={renderGroups()} initialState={initialState} tableWrapperProps={{ scrollContainerRef, scrollDependencies: [nodesSearchValue, storageNodesGroupByParam, tableGroups], loading: isLoading, className: b('groups-wrapper'), }} /> ); }