diff --git a/src/containers/Tenant/ObjectSummary/ObjectSummary.tsx b/src/containers/Tenant/ObjectSummary/ObjectSummary.tsx index 09d709532a..6786bad418 100644 --- a/src/containers/Tenant/ObjectSummary/ObjectSummary.tsx +++ b/src/containers/Tenant/ObjectSummary/ObjectSummary.tsx @@ -44,7 +44,7 @@ import {ObjectTree} from './ObjectTree'; import {SchemaActions} from './SchemaActions'; import i18n from './i18n'; import {b} from './shared'; -import {transformPath} from './transformPath'; +import {isDomain, transformPath} from './transformPath'; import './ObjectSummary.scss'; @@ -158,7 +158,11 @@ export function ObjectSummary({ const overview: InfoViewerItem[] = []; - overview.push({label: i18n('field_type'), value: PathType?.replace(/^EPathType/, '')}); + const normalizedType = isDomain(path, PathType) + ? 'Domain' + : PathType?.replace(/^EPathType/, ''); + + overview.push({label: i18n('field_type'), value: normalizedType}); if (PathSubType !== EPathSubType.EPathSubTypeEmpty) { overview.push({ @@ -353,6 +357,8 @@ export function ObjectSummary({ dispatchCommonInfoVisibilityState(PaneVisibilityActionTypes.clear); }; + const relativePath = transformPath(path, tenantName); + const renderCommonInfoControls = () => { const showPreview = isTableType(type) && !isIndexTableType(subType); return ( @@ -364,7 +370,7 @@ export function ObjectSummary({ 'm', )(path, 'preview')} @@ -380,15 +386,19 @@ export function ObjectSummary({ const renderEntityTypeBadge = () => { const {Status, Reason} = currentObjectData ?? {}; + if (type) { + let label = type.replace('EPathType', ''); + if (isDomain(path, type)) { + label = 'domain'; + } + return
{label}
; + } let message; - if (!type && Status && Reason) { + if (Status && Reason) { message = `${Status}: ${Reason}`; } - - return type ? ( -
{type.replace('EPathType', '')}
- ) : ( + return (
@@ -414,9 +424,7 @@ export function ObjectSummary({
{renderEntityTypeBadge()} -
- {transformPath(path, tenantName)} -
+
{relativePath}
{renderCommonInfoControls()} diff --git a/src/containers/Tenant/ObjectSummary/__test__/transformPath.test.ts b/src/containers/Tenant/ObjectSummary/__test__/transformPath.test.ts index 6161f52f6f..553675c4f6 100644 --- a/src/containers/Tenant/ObjectSummary/__test__/transformPath.test.ts +++ b/src/containers/Tenant/ObjectSummary/__test__/transformPath.test.ts @@ -1,4 +1,5 @@ -import {transformPath} from '../transformPath'; +import {EPathType} from '../../../../types/api/schema'; +import {isDomain, transformPath} from '../transformPath'; describe('transformPath', () => { test.each([ @@ -9,8 +10,8 @@ describe('transformPath', () => { ['/prod/v1/sth', 'prod/v1', 'sth'], ['/dev/v1/sth', '/dev', 'v1/sth'], ['/dev/v1/sth', 'dev', 'v1/sth'], - ['/dev', '/dev', '/'], - ['/dev', 'dev', '/'], + ['/dev', '/dev', '/dev'], + ['/dev', 'dev', '/dev'], ['/', '/dev', '/'], ['/', 'dev', '/'], ['', '/dev', '/'], @@ -41,3 +42,32 @@ describe('transformPath', () => { expect(transformPath('///dev/v1/sth', '/dev')).toBe('v1/sth'); }); }); + +describe('isDomain', () => { + it('should return true for valid domain paths', () => { + expect(isDomain('/domain', EPathType.EPathTypeDir)).toBe(true); + expect(isDomain('/another-domain', EPathType.EPathTypeDir)).toBe(true); + }); + + it('should return false for non-directory paths', () => { + expect(isDomain('/domain', EPathType.EPathTypeColumnStore)).toBe(false); + expect(isDomain('/domain', undefined)).toBe(false); + }); + + it('should return false for paths without slash', () => { + expect(isDomain('domain', EPathType.EPathTypeDir)).toBe(false); + }); + + it('should return false for paths with multiple slashes', () => { + expect(isDomain('/domain/subdomain', EPathType.EPathTypeDir)).toBe(false); + expect(isDomain('/domain/', EPathType.EPathTypeDir)).toBe(false); + }); + + it('should return false for empty paths', () => { + expect(isDomain('', EPathType.EPathTypeDir)).toBe(false); + }); + + it('should return true for root path', () => { + expect(isDomain('/', EPathType.EPathTypeDir)).toBe(true); + }); +}); diff --git a/src/containers/Tenant/ObjectSummary/transformPath.ts b/src/containers/Tenant/ObjectSummary/transformPath.ts index 5f6bb0faf8..e729069c16 100644 --- a/src/containers/Tenant/ObjectSummary/transformPath.ts +++ b/src/containers/Tenant/ObjectSummary/transformPath.ts @@ -1,3 +1,5 @@ +import {EPathType} from '../../../types/api/schema'; + export function transformPath(path: string, dbName: string): string { // Normalize the path and dbName by removing leading/trailing slashes const normalizedPath = path.replace(/^\/+|\/+$/g, ''); @@ -6,6 +8,9 @@ export function transformPath(path: string, dbName: string): string { if (!normalizedPath.startsWith(normalizedDbName)) { return normalizedPath || '/'; } + if (normalizedPath === normalizedDbName) { + return `/${normalizedPath}`; + } let result = normalizedPath.slice(normalizedDbName.length); @@ -14,3 +19,10 @@ export function transformPath(path: string, dbName: string): string { return result; } + +export function isDomain(path: string, type?: EPathType) { + if (type !== EPathType.EPathTypeDir) { + return false; + } + return path.split('/').length === 2 && path.startsWith('/'); +} diff --git a/src/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx b/src/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx index 3da78debe7..2f7d52c0ae 100644 --- a/src/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx +++ b/src/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx @@ -110,14 +110,18 @@ export function SchemaTree(props: SchemaTreeProps) { collapsed: false, }} fetchPath={fetchPath} - getActions={getActions(dispatch, { - setActivePath: onActivePathUpdate, - updateQueryExecutionSettings: (settings) => - setQueryExecutionSettings({...querySettings, ...settings}), - showCreateDirectoryDialog: createDirectoryFeatureAvailable - ? handleOpenCreateDirectoryDialog - : undefined, - })} + getActions={getActions( + dispatch, + { + setActivePath: onActivePathUpdate, + updateQueryExecutionSettings: (settings) => + setQueryExecutionSettings({...querySettings, ...settings}), + showCreateDirectoryDialog: createDirectoryFeatureAvailable + ? handleOpenCreateDirectoryDialog + : undefined, + }, + rootPath, + )} renderAdditionalNodeElements={getSchemaControls(dispatch, { setActivePath: onActivePathUpdate, })} diff --git a/src/containers/Tenant/utils/schemaActions.ts b/src/containers/Tenant/utils/schemaActions.ts index 755595c7e2..9035c3e340 100644 --- a/src/containers/Tenant/utils/schemaActions.ts +++ b/src/containers/Tenant/utils/schemaActions.ts @@ -6,6 +6,7 @@ import {TENANT_PAGES_IDS, TENANT_QUERY_TABS_ID} from '../../../store/reducers/te import {setQueryTab, setTenantPage} from '../../../store/reducers/tenant/tenant'; import type {QueryMode, QuerySettings} from '../../../types/store/query'; import createToast from '../../../utils/createToast'; +import {transformPath} from '../ObjectSummary/transformPath'; import i18n from '../i18n'; import { @@ -33,7 +34,7 @@ interface ActionsAdditionalEffects { } const bindActions = ( - path: string, + {path, relativePath}: {path: string; relativePath: string}, dispatch: React.Dispatch, additionalEffects: ActionsAdditionalEffects, ) => { @@ -45,7 +46,7 @@ const bindActions = ( updateQueryExecutionSettings({queryMode: mode}); } - dispatch(changeUserInput({input: tmpl(path)})); + dispatch(changeUserInput({input: tmpl(relativePath)})); dispatch(setTenantPage(TENANT_PAGES_IDS.query)); dispatch(setQueryTab(TENANT_QUERY_TABS_ID.newQuery)); setActivePath(path); @@ -75,7 +76,7 @@ const bindActions = ( dropView: inputQuery(dropViewTemplate, 'script'), copyPath: () => { try { - copy(path); + copy(relativePath); createToast({ name: 'Copied', title: i18n('actions.copied'), @@ -95,9 +96,10 @@ const bindActions = ( type ActionsSet = ReturnType['getActions']>; export const getActions = - (dispatch: React.Dispatch, additionalEffects: ActionsAdditionalEffects) => + (dispatch: React.Dispatch, additionalEffects: ActionsAdditionalEffects, rootPath = '') => (path: string, type: NavigationTreeNodeType) => { - const actions = bindActions(path, dispatch, additionalEffects); + const relativePath = transformPath(path, rootPath); + const actions = bindActions({path, relativePath}, dispatch, additionalEffects); const copyItem = {text: i18n('actions.copyPath'), action: actions.copyPath}; const DIR_SET: ActionsSet = [