diff --git a/src/containers/Cluster/Cluster.tsx b/src/containers/Cluster/Cluster.tsx
index 5f85018d36..b77a5cb500 100644
--- a/src/containers/Cluster/Cluster.tsx
+++ b/src/containers/Cluster/Cluster.tsx
@@ -9,7 +9,11 @@ import {AutoRefreshControl} from '../../components/AutoRefreshControl/AutoRefres
import {EntityStatus} from '../../components/EntityStatus/EntityStatus';
import {InternalLink} from '../../components/InternalLink';
import routes, {getLocationObjectFromHref} from '../../routes';
-import {clusterApi, updateDefaultClusterTab} from '../../store/reducers/cluster/cluster';
+import {
+ clusterApi,
+ selectClusterTitle,
+ updateDefaultClusterTab,
+} from '../../store/reducers/cluster/cluster';
import {setHeaderBreadcrumbs} from '../../store/reducers/header/header';
import type {
AdditionalClusterProps,
@@ -18,7 +22,6 @@ import type {
AdditionalVersionsProps,
} from '../../types/additionalProps';
import {cn} from '../../utils/cn';
-import {CLUSTER_DEFAULT_TITLE} from '../../utils/constants';
import {useTypedDispatch, useTypedSelector} from '../../utils/hooks';
import {parseVersionsToVersionToColorMap} from '../../utils/versions';
import {NodesWrapper} from '../Nodes/NodesWrapper';
@@ -58,6 +61,10 @@ export function Cluster({
backend: StringParam,
});
+ const clusterTitle = useTypedSelector((state) =>
+ selectClusterTitle(state, clusterName ?? undefined),
+ );
+
const {
data: {clusterData: cluster = {}, groupsStats} = {},
isLoading: infoLoading,
@@ -66,11 +73,9 @@ export function Cluster({
const clusterError = error && typeof error === 'object' ? error : undefined;
- const {Name} = cluster;
-
React.useEffect(() => {
dispatch(setHeaderBreadcrumbs('cluster', {}));
- }, [dispatch, Name]);
+ }, [dispatch]);
const versionToColor = React.useMemo(() => {
if (additionalVersionsProps?.getVersionToColorMap) {
@@ -88,13 +93,12 @@ export function Cluster({
);
};
- const clusterTitle = cluster?.Name ?? clusterName ?? CLUSTER_DEFAULT_TITLE;
const activeTab = React.useMemo(
() => clusterTabs.find(({id}) => id === activeTabId),
[activeTabId],
diff --git a/src/services/api.ts b/src/services/api.ts
index f7e26863ed..372ff94d48 100644
--- a/src/services/api.ts
+++ b/src/services/api.ts
@@ -14,12 +14,7 @@ import type {DescribeConsumerResult} from '../types/api/consumer';
import type {FeatureFlagConfigs} from '../types/api/featureFlags';
import type {HealthCheckAPIResponse} from '../types/api/healthcheck';
import type {JsonHotKeysResponse} from '../types/api/hotkeys';
-import type {
- MetaCluster,
- MetaClusters,
- MetaGeneralClusterInfo,
- MetaTenants,
-} from '../types/api/meta';
+import type {MetaBaseClusterInfo, MetaCluster, MetaClusters, MetaTenants} from '../types/api/meta';
import type {ModifyDiskResponse} from '../types/api/modifyDisk';
import type {TNetInfo} from '../types/api/netInfo';
import type {TNodesInfo} from '../types/api/nodes';
@@ -826,7 +821,7 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
getClusterBaseInfo(
_clusterName: string,
_opts: AxiosOptions = {},
- ): Promise {
+ ): Promise {
throw new Error('Method is not implemented.');
}
}
@@ -861,8 +856,8 @@ export class YdbWebVersionAPI extends YdbEmbeddedAPI {
getClusterBaseInfo(
clusterName: string,
{concurrentId, signal}: AxiosOptions = {},
- ): Promise {
- return this.get(
+ ): Promise {
+ return this.get(
`${META_BACKEND || ''}/meta/db_clusters`,
{
name: clusterName,
diff --git a/src/store/reducers/cluster/cluster.ts b/src/store/reducers/cluster/cluster.ts
index b5aa65b1ae..c10f5b07a8 100644
--- a/src/store/reducers/cluster/cluster.ts
+++ b/src/store/reducers/cluster/cluster.ts
@@ -1,4 +1,4 @@
-import {createSlice} from '@reduxjs/toolkit';
+import {createSelector, createSlice} from '@reduxjs/toolkit';
import type {Dispatch, PayloadAction} from '@reduxjs/toolkit';
import {skipToken} from '@reduxjs/toolkit/query';
import {StringParam, useQueryParam} from 'use-query-params';
@@ -7,12 +7,17 @@ import type {ClusterTab} from '../../../containers/Cluster/utils';
import {clusterTabsIds, isClusterTab} from '../../../containers/Cluster/utils';
import {parseTraceFields} from '../../../services/parsers/parseMetaCluster';
import type {TClusterInfo} from '../../../types/api/cluster';
-import {DEFAULT_CLUSTER_TAB_KEY} from '../../../utils/constants';
+import {CLUSTER_DEFAULT_TITLE, DEFAULT_CLUSTER_TAB_KEY} from '../../../utils/constants';
import {isQueryErrorResponse} from '../../../utils/query';
+import type {RootState} from '../../defaultStore';
import {api} from '../api';
import type {ClusterGroupsStats, ClusterState} from './types';
-import {createSelectClusterGroupsQuery, parseGroupsStatsQueryResponse} from './utils';
+import {
+ createSelectClusterGroupsQuery,
+ normalizeDomain,
+ parseGroupsStatsQueryResponse,
+} from './utils';
const defaultClusterTabLS = localStorage.getItem(DEFAULT_CLUSTER_TAB_KEY);
@@ -61,7 +66,6 @@ export const clusterApi = api.injectEndpoints({
const clusterData = await window.api.getClusterInfo(clusterName, {signal});
const clusterRoot = clusterData.Domain;
-
// Without domain we cannot get stats from system tables
if (!clusterRoot) {
return {data: {clusterData}};
@@ -134,3 +138,24 @@ export function useClusterBaseInfo() {
monitoring,
};
}
+
+const createClusterInfoSelector = createSelector(
+ (clusterName?: string) => clusterName,
+ (clusterName) => clusterApi.endpoints.getClusterInfo.select(clusterName),
+);
+
+export const selectClusterInfo = createSelector(
+ (state: RootState) => state,
+ (_state: RootState, clusterName?: string) => createClusterInfoSelector(clusterName),
+ (state, selectGetClusterInfo) => selectGetClusterInfo(state).data,
+);
+
+export const selectClusterTitle = createSelector(
+ (_state: RootState, clusterName?: string) => clusterName,
+ (state: RootState, clusterName?: string) => selectClusterInfo(state, clusterName),
+ (clusterName, clusterInfo) => {
+ const {Name, Domain} = clusterInfo?.clusterData || {};
+
+ return Name || clusterName || normalizeDomain(Domain) || CLUSTER_DEFAULT_TITLE;
+ },
+);
diff --git a/src/store/reducers/cluster/utils.ts b/src/store/reducers/cluster/utils.ts
index 16c3f7d3fa..2dc9c9d767 100644
--- a/src/store/reducers/cluster/utils.ts
+++ b/src/store/reducers/cluster/utils.ts
@@ -86,3 +86,11 @@ export const parseGroupsStatsQueryResponse = (
return result;
};
+
+export function normalizeDomain(domain?: string) {
+ if (!domain) {
+ return undefined;
+ }
+ const normalizedDomain = domain.startsWith('/') ? domain.slice(1) : domain;
+ return normalizedDomain.toUpperCase();
+}
diff --git a/src/types/api/meta.ts b/src/types/api/meta.ts
index 8142b78194..bf213bf6fe 100644
--- a/src/types/api/meta.ts
+++ b/src/types/api/meta.ts
@@ -22,7 +22,7 @@ export interface MetaExtendedClusterInfo extends MetaGeneralClusterInfo {
versions?: MetaClusterVersion[];
}
-export interface MetaGeneralClusterInfo {
+export interface MetaBaseClusterInfo {
owner?: string;
location?: string;
image?: string;
@@ -38,11 +38,14 @@ export interface MetaGeneralClusterInfo {
description?: string;
balancer?: string;
service?: string;
- cluster?: MetaViewerClusterInfo;
trace_view?: string;
trace_check?: string;
}
+export interface MetaGeneralClusterInfo extends MetaBaseClusterInfo {
+ cluster?: MetaViewerClusterInfo;
+}
+
// In case of error in viewer /cluster request mvp return error field instead of cluster data
export interface MetaViewerClusterInfo extends TClusterInfo {
error?: string;