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
44 changes: 37 additions & 7 deletions src/containers/Cluster/Cluster.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import type {
AdditionalTenantsProps,
} from '../../types/additionalProps';
import {EFlag} from '../../types/api/enums';
import {uiFactory} from '../../uiFactory/uiFactory';
import {cn} from '../../utils/cn';
import {useAutoRefreshInterval, useTypedDispatch, useTypedSelector} from '../../utils/hooks';
import {useAppTitle} from '../App/AppTitleContext';
Expand All @@ -39,7 +40,13 @@ import {VersionsContainer} from '../Versions/Versions';

import {ClusterOverview} from './ClusterOverview/ClusterOverview';
import type {ClusterTab} from './utils';
import {clusterTabs, clusterTabsIds, getClusterPath, isClusterTab} from './utils';
import {
clusterTabs,
clusterTabsIds,
getClusterPath,
isClusterTab,
useShouldShowEventsTab,
} from './utils';

import './Cluster.scss';

Expand All @@ -60,6 +67,7 @@ export function Cluster({
const isClusterDashboardAvailable = useClusterDashboardAvailable();

const shouldShowNetworkTable = useShouldShowClusterNetworkTable();
const shouldShowEventsTab = useShouldShowEventsTab();

const [autoRefreshInterval] = useAutoRefreshInterval();

Expand Down Expand Up @@ -99,12 +107,17 @@ export function Cluster({
}, [dispatch]);

const actualClusterTabs = React.useMemo(() => {
if (shouldShowNetworkTable) {
return clusterTabs;
} else {
return clusterTabs.filter((tab) => tab.id !== clusterTabsIds.network);
let tabs = clusterTabs;

if (!shouldShowNetworkTable) {
tabs = tabs.filter((tab) => tab.id !== clusterTabsIds.network);
}
}, [shouldShowNetworkTable]);
if (!shouldShowEventsTab) {
tabs = tabs.filter((tab) => tab.id !== clusterTabsIds.events);
}

return tabs;
}, [shouldShowEventsTab, shouldShowNetworkTable]);

const getClusterTitle = () => {
if (infoLoading) {
Expand Down Expand Up @@ -240,6 +253,17 @@ export function Cluster({
>
<VersionsContainer cluster={cluster} loading={infoLoading} />
</Route>
{shouldShowEventsTab && (
<Route
path={
getLocationObjectFromHref(getClusterPath(clusterTabsIds.events))
.pathname
}
>
{uiFactory.renderEvents?.()}
</Route>
)}

<Route
render={() => (
<Redirect to={getLocationObjectFromHref(getClusterPath(activeTabId))} />
Expand All @@ -257,13 +281,19 @@ function useClusterTab() {
const defaultTab = useTypedSelector((state) => state.cluster.defaultClusterTab);

const shouldShowNetworkTable = useShouldShowClusterNetworkTable();
const shouldShowEventsTab = useShouldShowEventsTab();

const match = useRouteMatch<{activeTab: string}>(routes.cluster);

const {activeTab: activeTabFromParams} = match?.params || {};
let activeTab: ClusterTab;

if (!shouldShowNetworkTable && activeTabFromParams === clusterTabsIds.network) {
const shouldSwitchFromNetworkToDefault =
!shouldShowNetworkTable && activeTabFromParams === clusterTabsIds.network;
const shouldSwitchFromEventsToDefault =
!shouldShowEventsTab && activeTabFromParams === clusterTabsIds.events;

if (shouldSwitchFromNetworkToDefault || shouldSwitchFromEventsToDefault) {
activeTab = INITIAL_DEFAULT_CLUSTER_TAB;
} else if (isClusterTab(activeTabFromParams)) {
activeTab = activeTabFromParams;
Expand Down
10 changes: 9 additions & 1 deletion src/containers/Cluster/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,13 @@
"context_cpu-description": "CPU load is calculated as the cumulative usage across all actor system pools on all nodes in the cluster",
"context_memory-description": "Memory usage is the total memory consumed by all nodes in the cluster",
"context_storage-description": "Storage usage is a cumulative usage of raw disk space of all media types",
"context_network-description": "Network usage is the average outgoing bandwidth usage across all nodes in the cluster"
"context_network-description": "Network usage is the average outgoing bandwidth usage across all nodes in the cluster",

"tab_databases": "Databases",
"tab_nodes": "Nodes",
"tab_storage": "Storage",
"tab_network": "Network",
"tab_versions": "Versions",
"tab_tablets": "Tablets",
"tab_events": "Events"
}
41 changes: 34 additions & 7 deletions src/containers/Cluster/utils.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import type {CreateHrefOptions} from '../../routes';
import routes, {createHref} from '../../routes';
import {useClusterEventsAvailable} from '../../store/reducers/capabilities/hooks';
import type {ClusterGroupsStats} from '../../store/reducers/cluster/types';
import type {ValueOf} from '../../types/common';
import {uiFactory} from '../../uiFactory/uiFactory';

import i18n from './i18n';

export const clusterTabsIds = {
tenants: 'tenants',
Expand All @@ -10,36 +14,55 @@ export const clusterTabsIds = {
network: 'network',
versions: 'versions',
tablets: 'tablets',
events: 'events',
} as const;

export type ClusterTab = ValueOf<typeof clusterTabsIds>;

const tenants = {
id: clusterTabsIds.tenants,
title: 'Databases',
get title() {
return i18n('tab_databases');
},
};
const nodes = {
id: clusterTabsIds.nodes,
title: 'Nodes',
get title() {
return i18n('tab_nodes');
},
};
const storage = {
id: clusterTabsIds.storage,
title: 'Storage',
get title() {
return i18n('tab_storage');
},
};
const network = {
id: clusterTabsIds.network,
title: 'Network',
get title() {
return i18n('tab_network');
},
};
const versions = {
id: clusterTabsIds.versions,
title: 'Versions',
get title() {
return i18n('tab_versions');
},
};
const tablets = {
id: clusterTabsIds.tablets,
title: 'Tablets',
get title() {
return i18n('tab_tablets');
},
};
const events = {
Copy link

Copilot AI Aug 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The events tab title should be internationalized. Consider adding an i18n key for 'Events' instead of hardcoding the string.

Copilot uses AI. Check for mistakes.
id: clusterTabsIds.events,
get title() {
return i18n('tab_events');
},
};

export const clusterTabs = [tenants, nodes, storage, network, tablets, versions];
export const clusterTabs = [tenants, nodes, storage, network, tablets, versions, events];

export function isClusterTab(tab: any): tab is ClusterTab {
return Object.values(clusterTabsIds).includes(tab);
Expand All @@ -58,3 +81,7 @@ export const getTotalStorageGroupsUsed = (groupStats: ClusterGroupsStats) => {
return acc;
}, 0);
};

export function useShouldShowEventsTab() {
return useClusterEventsAvailable() && uiFactory.renderEvents;
}
4 changes: 4 additions & 0 deletions src/store/reducers/capabilities/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,3 +157,7 @@ export const useEditClusterFeatureAvailable = () => {
export const useDeleteClusterFeatureAvailable = () => {
return useGetMetaFeatureVersion('/meta/delete_cluster') >= 1;
};

export const useClusterEventsAvailable = () => {
return useGetMetaFeatureVersion('/meta/events') >= 1;
};
3 changes: 2 additions & 1 deletion src/types/api/capabilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,5 @@ export type MetaCapability =
| '/meta/stop_database'
| '/meta/create_cluster'
| '/meta/update_cluster'
| '/meta/delete_cluster';
| '/meta/delete_cluster'
| '/meta/events';
2 changes: 2 additions & 0 deletions src/uiFactory/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ export interface UIFactory<H extends string = CommonIssueType> {
scrollContainerRef: React.RefObject<HTMLDivElement>;
}) => React.ReactNode;

renderEvents?: () => React.ReactNode;

healthcheck: {
getHealthckechViewTitles: GetHealthcheckViewTitles<H>;
getHealthcheckViewsOrder: GetHealthcheckViewsOrder<H>;
Expand Down
Loading