Skip to content

Commit 418d3d8

Browse files
authored
feat: use relative entity path in schema actions (#1366)
1 parent 6cab2df commit 418d3d8

File tree

5 files changed

+83
-27
lines changed

5 files changed

+83
-27
lines changed

src/containers/Tenant/ObjectSummary/ObjectSummary.tsx

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ import {ObjectTree} from './ObjectTree';
4444
import {SchemaActions} from './SchemaActions';
4545
import i18n from './i18n';
4646
import {b} from './shared';
47-
import {transformPath} from './transformPath';
47+
import {isDomain, transformPath} from './transformPath';
4848

4949
import './ObjectSummary.scss';
5050

@@ -158,7 +158,11 @@ export function ObjectSummary({
158158

159159
const overview: InfoViewerItem[] = [];
160160

161-
overview.push({label: i18n('field_type'), value: PathType?.replace(/^EPathType/, '')});
161+
const normalizedType = isDomain(path, PathType)
162+
? 'Domain'
163+
: PathType?.replace(/^EPathType/, '');
164+
165+
overview.push({label: i18n('field_type'), value: normalizedType});
162166

163167
if (PathSubType !== EPathSubType.EPathSubTypeEmpty) {
164168
overview.push({
@@ -353,6 +357,8 @@ export function ObjectSummary({
353357
dispatchCommonInfoVisibilityState(PaneVisibilityActionTypes.clear);
354358
};
355359

360+
const relativePath = transformPath(path, tenantName);
361+
356362
const renderCommonInfoControls = () => {
357363
const showPreview = isTableType(type) && !isIndexTableType(subType);
358364
return (
@@ -364,7 +370,7 @@ export function ObjectSummary({
364370
'm',
365371
)(path, 'preview')}
366372
<ClipboardButton
367-
text={path}
373+
text={relativePath}
368374
view="flat-secondary"
369375
title={i18n('action_copySchemaPath')}
370376
/>
@@ -380,15 +386,19 @@ export function ObjectSummary({
380386

381387
const renderEntityTypeBadge = () => {
382388
const {Status, Reason} = currentObjectData ?? {};
389+
if (type) {
390+
let label = type.replace('EPathType', '');
391+
if (isDomain(path, type)) {
392+
label = 'domain';
393+
}
394+
return <div className={b('entity-type')}>{label}</div>;
395+
}
383396

384397
let message;
385-
if (!type && Status && Reason) {
398+
if (Status && Reason) {
386399
message = `${Status}: ${Reason}`;
387400
}
388-
389-
return type ? (
390-
<div className={b('entity-type')}>{type.replace('EPathType', '')}</div>
391-
) : (
401+
return (
392402
<div className={b('entity-type', {error: true})}>
393403
<HelpPopover content={message} offset={{left: 0}} />
394404
</div>
@@ -414,9 +424,7 @@ export function ObjectSummary({
414424
<div className={b('info-header')}>
415425
<div className={b('info-title')}>
416426
{renderEntityTypeBadge()}
417-
<div className={b('path-name')}>
418-
{transformPath(path, tenantName)}
419-
</div>
427+
<div className={b('path-name')}>{relativePath}</div>
420428
</div>
421429
<div className={b('info-controls')}>
422430
{renderCommonInfoControls()}

src/containers/Tenant/ObjectSummary/__test__/transformPath.test.ts

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import {transformPath} from '../transformPath';
1+
import {EPathType} from '../../../../types/api/schema';
2+
import {isDomain, transformPath} from '../transformPath';
23

34
describe('transformPath', () => {
45
test.each([
@@ -9,8 +10,8 @@ describe('transformPath', () => {
910
['/prod/v1/sth', 'prod/v1', 'sth'],
1011
['/dev/v1/sth', '/dev', 'v1/sth'],
1112
['/dev/v1/sth', 'dev', 'v1/sth'],
12-
['/dev', '/dev', '/'],
13-
['/dev', 'dev', '/'],
13+
['/dev', '/dev', '/dev'],
14+
['/dev', 'dev', '/dev'],
1415
['/', '/dev', '/'],
1516
['/', 'dev', '/'],
1617
['', '/dev', '/'],
@@ -41,3 +42,32 @@ describe('transformPath', () => {
4142
expect(transformPath('///dev/v1/sth', '/dev')).toBe('v1/sth');
4243
});
4344
});
45+
46+
describe('isDomain', () => {
47+
it('should return true for valid domain paths', () => {
48+
expect(isDomain('/domain', EPathType.EPathTypeDir)).toBe(true);
49+
expect(isDomain('/another-domain', EPathType.EPathTypeDir)).toBe(true);
50+
});
51+
52+
it('should return false for non-directory paths', () => {
53+
expect(isDomain('/domain', EPathType.EPathTypeColumnStore)).toBe(false);
54+
expect(isDomain('/domain', undefined)).toBe(false);
55+
});
56+
57+
it('should return false for paths without slash', () => {
58+
expect(isDomain('domain', EPathType.EPathTypeDir)).toBe(false);
59+
});
60+
61+
it('should return false for paths with multiple slashes', () => {
62+
expect(isDomain('/domain/subdomain', EPathType.EPathTypeDir)).toBe(false);
63+
expect(isDomain('/domain/', EPathType.EPathTypeDir)).toBe(false);
64+
});
65+
66+
it('should return false for empty paths', () => {
67+
expect(isDomain('', EPathType.EPathTypeDir)).toBe(false);
68+
});
69+
70+
it('should return true for root path', () => {
71+
expect(isDomain('/', EPathType.EPathTypeDir)).toBe(true);
72+
});
73+
});

src/containers/Tenant/ObjectSummary/transformPath.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import {EPathType} from '../../../types/api/schema';
2+
13
export function transformPath(path: string, dbName: string): string {
24
// Normalize the path and dbName by removing leading/trailing slashes
35
const normalizedPath = path.replace(/^\/+|\/+$/g, '');
@@ -6,6 +8,9 @@ export function transformPath(path: string, dbName: string): string {
68
if (!normalizedPath.startsWith(normalizedDbName)) {
79
return normalizedPath || '/';
810
}
11+
if (normalizedPath === normalizedDbName) {
12+
return `/${normalizedPath}`;
13+
}
914

1015
let result = normalizedPath.slice(normalizedDbName.length);
1116

@@ -14,3 +19,10 @@ export function transformPath(path: string, dbName: string): string {
1419

1520
return result;
1621
}
22+
23+
export function isDomain(path: string, type?: EPathType) {
24+
if (type !== EPathType.EPathTypeDir) {
25+
return false;
26+
}
27+
return path.split('/').length === 2 && path.startsWith('/');
28+
}

src/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -110,14 +110,18 @@ export function SchemaTree(props: SchemaTreeProps) {
110110
collapsed: false,
111111
}}
112112
fetchPath={fetchPath}
113-
getActions={getActions(dispatch, {
114-
setActivePath: onActivePathUpdate,
115-
updateQueryExecutionSettings: (settings) =>
116-
setQueryExecutionSettings({...querySettings, ...settings}),
117-
showCreateDirectoryDialog: createDirectoryFeatureAvailable
118-
? handleOpenCreateDirectoryDialog
119-
: undefined,
120-
})}
113+
getActions={getActions(
114+
dispatch,
115+
{
116+
setActivePath: onActivePathUpdate,
117+
updateQueryExecutionSettings: (settings) =>
118+
setQueryExecutionSettings({...querySettings, ...settings}),
119+
showCreateDirectoryDialog: createDirectoryFeatureAvailable
120+
? handleOpenCreateDirectoryDialog
121+
: undefined,
122+
},
123+
rootPath,
124+
)}
121125
renderAdditionalNodeElements={getSchemaControls(dispatch, {
122126
setActivePath: onActivePathUpdate,
123127
})}

src/containers/Tenant/utils/schemaActions.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {TENANT_PAGES_IDS, TENANT_QUERY_TABS_ID} from '../../../store/reducers/te
66
import {setQueryTab, setTenantPage} from '../../../store/reducers/tenant/tenant';
77
import type {QueryMode, QuerySettings} from '../../../types/store/query';
88
import createToast from '../../../utils/createToast';
9+
import {transformPath} from '../ObjectSummary/transformPath';
910
import i18n from '../i18n';
1011

1112
import {
@@ -33,7 +34,7 @@ interface ActionsAdditionalEffects {
3334
}
3435

3536
const bindActions = (
36-
path: string,
37+
{path, relativePath}: {path: string; relativePath: string},
3738
dispatch: React.Dispatch<any>,
3839
additionalEffects: ActionsAdditionalEffects,
3940
) => {
@@ -45,7 +46,7 @@ const bindActions = (
4546
updateQueryExecutionSettings({queryMode: mode});
4647
}
4748

48-
dispatch(changeUserInput({input: tmpl(path)}));
49+
dispatch(changeUserInput({input: tmpl(relativePath)}));
4950
dispatch(setTenantPage(TENANT_PAGES_IDS.query));
5051
dispatch(setQueryTab(TENANT_QUERY_TABS_ID.newQuery));
5152
setActivePath(path);
@@ -75,7 +76,7 @@ const bindActions = (
7576
dropView: inputQuery(dropViewTemplate, 'script'),
7677
copyPath: () => {
7778
try {
78-
copy(path);
79+
copy(relativePath);
7980
createToast({
8081
name: 'Copied',
8182
title: i18n('actions.copied'),
@@ -95,9 +96,10 @@ const bindActions = (
9596
type ActionsSet = ReturnType<Required<NavigationTreeProps>['getActions']>;
9697

9798
export const getActions =
98-
(dispatch: React.Dispatch<any>, additionalEffects: ActionsAdditionalEffects) =>
99+
(dispatch: React.Dispatch<any>, additionalEffects: ActionsAdditionalEffects, rootPath = '') =>
99100
(path: string, type: NavigationTreeNodeType) => {
100-
const actions = bindActions(path, dispatch, additionalEffects);
101+
const relativePath = transformPath(path, rootPath);
102+
const actions = bindActions({path, relativePath}, dispatch, additionalEffects);
101103
const copyItem = {text: i18n('actions.copyPath'), action: actions.copyPath};
102104

103105
const DIR_SET: ActionsSet = [

0 commit comments

Comments
 (0)