Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions src/components/EntityStatus/EntityStatus.scss
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,4 @@
color: var(--ydb-color-status-red);
}
}

&__info-popover {
padding: var(--g-spacing-4);
}
}
3 changes: 2 additions & 1 deletion src/components/EntityStatus/EntityStatus.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {Button, ClipboardButton, Icon, Popover, Link as UIKitLink} from '@gravit

import {EFlag} from '../../types/api/enums';
import {cn} from '../../utils/cn';
import {YDB_POPOVER_CLASS_NAME} from '../../utils/constants';
import {InternalLink} from '../InternalLink/InternalLink';
import {StatusIcon} from '../StatusIcon/StatusIcon';
import type {StatusIconMode, StatusIconSize} from '../StatusIcon/StatusIcon';
Expand Down Expand Up @@ -120,7 +121,7 @@ export function EntityStatus({
>
{infoPopoverContent && (
<Popover
className={b('info-popover')}
className={YDB_POPOVER_CLASS_NAME}
content={infoPopoverContent}
placement={['top-start', 'bottom-start']}
onOpenChange={(visible) => setInfoIconHovered(visible)}
Expand Down
3 changes: 0 additions & 3 deletions src/components/HoverPopup/HoverPopup.scss

This file was deleted.

8 changes: 2 additions & 6 deletions src/components/HoverPopup/HoverPopup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,10 @@ import type {PopupProps} from '@gravity-ui/uikit';
import {Popup} from '@gravity-ui/uikit';
import debounce from 'lodash/debounce';

import {cn} from '../../utils/cn';

import './HoverPopup.scss';
import {YDB_POPOVER_CLASS_NAME} from '../../utils/constants';

const DEBOUNCE_TIMEOUT = 100;

const b = cn('ydb-hover-popup');

type HoverPopupProps = {
children: React.ReactNode;
renderPopupContent: () => React.ReactNode;
Expand Down Expand Up @@ -112,7 +108,7 @@ export const HoverPopup = ({
// bigger offset for easier switching to neighbour nodes
// matches the default offset for popup with arrow out of a sense of beauty
offset={offset || {mainAxis: 12, crossAxis: 0}}
className={b()}
className={YDB_POPOVER_CLASS_NAME}
>
<div
className={contentClassName}
Expand Down
3 changes: 0 additions & 3 deletions src/components/SpeedMultiMeter/SpeedMultiMeter.scss
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,6 @@
font-size: 18px;
line-height: 24px;
}
&__popover-content {
padding: var(--g-spacing-4);
}

&__popover-row {
display: block;
Expand Down
3 changes: 2 additions & 1 deletion src/components/SpeedMultiMeter/SpeedMultiMeter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {Popover} from '@gravity-ui/uikit';
import type {BytesSizes, ProcessSpeedStats} from '../../utils/bytesParsers';
import {formatBytes} from '../../utils/bytesParsers';
import {cn} from '../../utils/cn';
import {YDB_POPOVER_CLASS_NAME} from '../../utils/constants';

import i18n from './i18n';

Expand Down Expand Up @@ -105,7 +106,7 @@ export const SpeedMultiMeter = ({
)}
<Popover
content={renderPopoverContent()}
className={b('popover-container')}
className={b('popover-container', YDB_POPOVER_CLASS_NAME)}
placement={'bottom'}
disabled={!withPopover}
hasArrow={true}
Expand Down
4 changes: 4 additions & 0 deletions src/containers/App/App.scss
Original file line number Diff line number Diff line change
Expand Up @@ -123,3 +123,7 @@ body,

height: 100%;
}

.ydb-popover {
padding: var(--g-spacing-4);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {ShieldKeyhole} from '@gravity-ui/icons';
import DataTable from '@gravity-ui/react-data-table';
import {Icon, Label, Popover} from '@gravity-ui/uikit';
import {Flex, Icon, Label, Popover} from '@gravity-ui/uikit';

import {CellWithPopover} from '../../../../components/CellWithPopover/CellWithPopover';
import {EntityStatus} from '../../../../components/EntityStatus/EntityStatus';
Expand All @@ -9,7 +9,7 @@ import {UsageLabel} from '../../../../components/UsageLabel/UsageLabel';
import {getStorageGroupPath} from '../../../../routes';
import {valueIsDefined} from '../../../../utils';
import {cn} from '../../../../utils/cn';
import {EMPTY_DATA_PLACEHOLDER} from '../../../../utils/constants';
import {EMPTY_DATA_PLACEHOLDER, YDB_POPOVER_CLASS_NAME} from '../../../../utils/constants';
import {formatNumber} from '../../../../utils/dataFormatters/dataFormatters';
import {getUsageSeverity} from '../../../../utils/generateEvaluator';
import {formatToMs} from '../../../../utils/timeParsers';
Expand Down Expand Up @@ -58,17 +58,22 @@ const typeColumn: StorageGroupsColumn = {
resizeMinWidth: 100,
align: DataTable.LEFT,
render: ({row}) => (
<div>
<Flex>
<Label>{row.MediaType || '—'}</Label>
{'\u00a0'}
{row.Encryption && (
<Popover content={i18n('encrypted')} placement="right" openDelay={0}>
<Popover
content={i18n('encrypted')}
placement="right"
openDelay={0}
className={YDB_POPOVER_CLASS_NAME}
>
<Label>
<Icon data={ShieldKeyhole} size={18} />
</Label>
</Popover>
)}
</div>
</Flex>
),
sortable: false,
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import {InfoViewer} from '../../../../../components/InfoViewer/InfoViewer';
import {ProgressWrapper} from '../../../../../components/ProgressWrapper';
import {TENANT_DIAGNOSTICS_TABS_IDS} from '../../../../../store/reducers/tenant/constants';
import type {TMemoryStats} from '../../../../../types/api/nodes';
import {cn} from '../../../../../utils/cn';
import {formatStorageValuesToGb} from '../../../../../utils/dataFormatters/dataFormatters';
import {useSearchQuery} from '../../../../../utils/hooks';
import {TenantTabsGroups, getTenantPath} from '../../../TenantPages';
import {StatsWrapper} from '../StatsWrapper/StatsWrapper';
import {TenantDashboard} from '../TenantDashboard/TenantDashboard';
import i18n from '../i18n';

Expand All @@ -27,6 +31,7 @@ export function TenantMemory({
memoryUsed,
memoryLimit,
}: TenantMemoryProps) {
const query = useSearchQuery();
const renderMemoryDetails = () => {
if (memoryStats) {
return <MemoryDetailsSection memoryStats={memoryStats} />;
Expand Down Expand Up @@ -61,7 +66,16 @@ export function TenantMemory({
<div className={b()}>
<TenantDashboard database={tenantName} charts={memoryDashboardConfig} />
{renderMemoryDetails()}
<TopNodesByMemory tenantName={tenantName} />

<StatsWrapper
title={i18n('title_top-nodes-by-memory')}
allEntitiesLink={getTenantPath({
...query,
[TenantTabsGroups.diagnosticsTab]: TENANT_DIAGNOSTICS_TABS_IDS.nodes,
})}
>
<TopNodesByMemory tenantName={tenantName} />
</StatsWrapper>
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,15 @@ import {
import type {GetNodesColumnsParams} from '../../../../../components/nodesColumns/types';
import {nodesApi} from '../../../../../store/reducers/nodes/nodes';
import type {NodesPreparedEntity} from '../../../../../store/reducers/nodes/types';
import {TENANT_DIAGNOSTICS_TABS_IDS} from '../../../../../store/reducers/tenant/constants';
import type {AdditionalNodesProps} from '../../../../../types/additionalProps';
import type {NodesRequiredField} from '../../../../../types/api/nodes';
import {
TENANT_OVERVIEW_TABLES_LIMIT,
TENANT_OVERVIEW_TABLES_SETTINGS,
} from '../../../../../utils/constants';
import {useAutoRefreshInterval, useSearchQuery} from '../../../../../utils/hooks';
import {useAutoRefreshInterval} from '../../../../../utils/hooks';
import {getRequiredDataFields} from '../../../../../utils/tableUtils/getRequiredDataFields';
import {TenantTabsGroups, getTenantPath} from '../../../TenantPages';
import {TenantOverviewTableLayout} from '../TenantOverviewTableLayout';
import {getSectionTitle} from '../getSectionTitle';
import i18n from '../i18n';

function getTopNodesByMemoryColumns(
Expand Down Expand Up @@ -56,8 +53,6 @@ interface TopNodesByMemoryProps {
}

export function TopNodesByMemory({tenantName, additionalNodesProps}: TopNodesByMemoryProps) {
const query = useSearchQuery();

const [autoRefreshInterval] = useAutoRefreshInterval();
const [columns, fieldsRequired] = getTopNodesByMemoryColumns({
getNodeRef: additionalNodesProps?.getNodeRef,
Expand All @@ -80,22 +75,8 @@ export function TopNodesByMemory({tenantName, additionalNodesProps}: TopNodesByM

const topNodes = currentData?.Nodes || [];

const title = getSectionTitle({
entity: i18n('nodes'),
postfix: i18n('by-memory'),
link: getTenantPath({
...query,
[TenantTabsGroups.diagnosticsTab]: TENANT_DIAGNOSTICS_TABS_IDS.nodes,
}),
});

return (
<TenantOverviewTableLayout
title={title}
loading={loading}
error={error}
withData={Boolean(currentData)}
>
<TenantOverviewTableLayout loading={loading} error={error} withData={Boolean(currentData)}>
<ResizeableDataTable
columnsWidthLSKey={NODES_COLUMNS_WIDTH_LS_KEY}
data={topNodes}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,74 +1,53 @@
import {Flex, Tab, TabList, TabProvider} from '@gravity-ui/uikit';
import {Flex} from '@gravity-ui/uikit';

import {TENANT_NETWORK_TABS_IDS} from '../../../../../store/reducers/tenant/constants';
import {TENANT_DIAGNOSTICS_TABS_IDS} from '../../../../../store/reducers/tenant/constants';
import type {AdditionalNodesProps} from '../../../../../types/additionalProps';
import {cn} from '../../../../../utils/cn';
import {ENABLE_NETWORK_TABLE_KEY} from '../../../../../utils/constants';
import {useSearchQuery, useSetting} from '../../../../../utils/hooks';
import {TenantTabsGroups, getTenantPath} from '../../../TenantPages';
import {StatsWrapper} from '../StatsWrapper/StatsWrapper';
import i18n from '../i18n';

import {TopNodesByPing} from './TopNodesByPing';
import {TopNodesBySkew} from './TopNodesBySkew';
import {useTenantNetworkQueryParams} from './useTenantNetworkQueryParams';

import './TenantNetwork.scss';

const b = cn('tenant-network');

const networkTabs = [
{id: TENANT_NETWORK_TABS_IDS.ping, title: i18n('title_nodes-by-ping')},
{id: TENANT_NETWORK_TABS_IDS.skew, title: i18n('title_nodes-by-skew')},
];

interface TenantNetworkProps {
tenantName: string;
additionalNodesProps?: AdditionalNodesProps;
}

export function TenantNetwork({tenantName, additionalNodesProps}: TenantNetworkProps) {
const {networkTab, handleNetworkTabChange} = useTenantNetworkQueryParams();
const query = useSearchQuery();
const [networkTableEnabled] = useSetting(ENABLE_NETWORK_TABLE_KEY);

const tab = networkTableEnabled
? {[TenantTabsGroups.diagnosticsTab]: TENANT_DIAGNOSTICS_TABS_IDS.network}
: {[TenantTabsGroups.diagnosticsTab]: TENANT_DIAGNOSTICS_TABS_IDS.nodes};

const renderTabContent = () => {
switch (networkTab) {
case TENANT_NETWORK_TABS_IDS.ping: {
return (
<TopNodesByPing
tenantName={tenantName}
additionalNodesProps={additionalNodesProps}
/>
);
}
case TENANT_NETWORK_TABS_IDS.skew: {
return (
<TopNodesBySkew
tenantName={tenantName}
additionalNodesProps={additionalNodesProps}
/>
);
}
default: {
return null;
}
}
};
const allNodesLink = getTenantPath({
...query,
...tab,
});

return (
<Flex direction="column" gap={4} className={b()}>
<Flex direction="column" gap={3} className={b('tabs-container')}>
<TabProvider value={networkTab}>
<TabList size="m">
{networkTabs.map(({id, title}) => {
return (
<Tab key={id} value={id} onClick={() => handleNetworkTabChange(id)}>
{title}
</Tab>
);
})}
</TabList>
</TabProvider>

<Flex direction="column" className={b('tab-content')}>
{renderTabContent()}
</Flex>
</Flex>
<StatsWrapper title={i18n('title_nodes-by-ping')} allEntitiesLink={allNodesLink}>
<TopNodesByPing
tenantName={tenantName}
additionalNodesProps={additionalNodesProps}
/>
</StatsWrapper>
<StatsWrapper title={i18n('title_nodes-by-skew')} allEntitiesLink={allNodesLink}>
<TopNodesBySkew
tenantName={tenantName}
additionalNodesProps={additionalNodesProps}
/>
</StatsWrapper>
</Flex>
);
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
import {ResizeableDataTable} from '../../../../../components/ResizeableDataTable/ResizeableDataTable';
import {NODES_COLUMNS_WIDTH_LS_KEY} from '../../../../../components/nodesColumns/constants';
import {nodesApi} from '../../../../../store/reducers/nodes/nodes';
import {TENANT_DIAGNOSTICS_TABS_IDS} from '../../../../../store/reducers/tenant/constants';
import type {AdditionalNodesProps} from '../../../../../types/additionalProps';
import {
TENANT_OVERVIEW_TABLES_LIMIT,
TENANT_OVERVIEW_TABLES_SETTINGS,
} from '../../../../../utils/constants';
import {useAutoRefreshInterval, useSearchQuery} from '../../../../../utils/hooks';
import {TenantTabsGroups, getTenantPath} from '../../../TenantPages';
import {useAutoRefreshInterval} from '../../../../../utils/hooks';
import {TenantOverviewTableLayout} from '../TenantOverviewTableLayout';
import {getSectionTitle} from '../getSectionTitle';
import i18n from '../i18n';

import {getTopNodesByPingColumns} from './columns';
Expand All @@ -21,7 +18,6 @@ interface TopNodesByPingProps {
}

export function TopNodesByPing({tenantName, additionalNodesProps}: TopNodesByPingProps) {
const query = useSearchQuery();
const [autoRefreshInterval] = useAutoRefreshInterval();
const [columns, fieldsRequired] = getTopNodesByPingColumns({
getNodeRef: additionalNodesProps?.getNodeRef,
Expand All @@ -43,22 +39,8 @@ export function TopNodesByPing({tenantName, additionalNodesProps}: TopNodesByPin
const loading = isFetching && currentData === undefined;
const topNodes = currentData?.Nodes || [];

const title = getSectionTitle({
entity: i18n('nodes'),
postfix: i18n('by-ping'),
link: getTenantPath({
...query,
[TenantTabsGroups.diagnosticsTab]: TENANT_DIAGNOSTICS_TABS_IDS.nodes,
}),
});

return (
<TenantOverviewTableLayout
title={title}
loading={loading}
error={error}
withData={Boolean(currentData)}
>
<TenantOverviewTableLayout loading={loading} error={error} withData={Boolean(currentData)}>
<ResizeableDataTable
columnsWidthLSKey={NODES_COLUMNS_WIDTH_LS_KEY}
data={topNodes}
Expand Down
Loading
Loading