Skip to content

Commit 669f7f0

Browse files
feat: add ReadOnly label to replicated tables (#970)
1 parent 071b0a7 commit 669f7f0

File tree

10 files changed

+50
-15
lines changed

10 files changed

+50
-15
lines changed

src/components/InfoViewer/InfoViewer.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import React from 'react';
22

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

5+
import i18n from './i18n';
6+
57
import './InfoViewer.scss';
68

79
export interface InfoViewerItem {
@@ -10,7 +12,7 @@ export interface InfoViewerItem {
1012
}
1113

1214
export interface InfoViewerProps {
13-
title?: string;
15+
title?: React.ReactNode;
1416
info?: InfoViewerItem[];
1517
dots?: boolean;
1618
size?: 's';
@@ -53,7 +55,7 @@ export const InfoViewer = ({
5355
))}
5456
</div>
5557
) : (
56-
<React.Fragment>No {title} data</React.Fragment>
58+
i18n('no-data')
5759
)}
5860
</div>
5961
);
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
22
"common.created": "Created",
3-
"common.type": "Type"
3+
"common.type": "Type",
4+
"no-data": "No data"
45
}
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import {registerKeysets} from '../../../utils/i18n';
22

33
import en from './en.json';
4-
import ru from './ru.json';
54

65
const COMPONENT = 'ydb-components-info-viewer';
76

8-
export default registerKeysets(COMPONENT, {ru, en});
7+
export default registerKeysets(COMPONENT, {en});

src/components/InfoViewer/i18n/ru.json

Lines changed: 0 additions & 4 deletions
This file was deleted.

src/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {InfoViewer} from '../../../../../components/InfoViewer';
44
import type {KeyValueRow} from '../../../../../types/api/query';
55
import type {EPathType, TEvDescribeSchemeResult} from '../../../../../types/api/schema';
66
import {cn} from '../../../../../utils/cn';
7-
import {getEntityName} from '../../../utils';
7+
import {EntityTitle} from '../../../EntityTitle/EntityTitle';
88

99
import i18n from './i18n';
1010
import {prepareTableInfo} from './prepareTableInfo';
@@ -20,7 +20,7 @@ interface TableInfoProps {
2020
}
2121

2222
export const TableInfo = ({data, type, olapStats}: TableInfoProps) => {
23-
const entityName = getEntityName(data?.PathDescription);
23+
const title = <EntityTitle data={data?.PathDescription} />;
2424

2525
const {
2626
generalInfo = [],
@@ -33,9 +33,9 @@ export const TableInfo = ({data, type, olapStats}: TableInfoProps) => {
3333
<div className={b()}>
3434
<InfoViewer
3535
info={generalInfo}
36-
title={entityName}
36+
title={title}
3737
className={b('info-block')}
38-
renderEmptyState={() => <div className={b('title')}>{entityName}</div>}
38+
renderEmptyState={() => <div className={b('title')}>{title}</div>}
3939
/>
4040
<div className={b('row')}>
4141
<div className={b('col')}>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import {Flex, Label} from '@gravity-ui/uikit';
2+
3+
import type {TPathDescription} from '../../../types/api/schema';
4+
import i18n from '../i18n';
5+
import {getEntityName, isReadOnlyTable} from '../utils';
6+
7+
interface EntityTitleProps {
8+
data?: TPathDescription;
9+
}
10+
11+
export function EntityTitle({data}: EntityTitleProps) {
12+
const entityName = getEntityName(data);
13+
14+
if (isReadOnlyTable(data)) {
15+
return (
16+
<Flex gap={1} wrap={'nowrap'}>
17+
{entityName} <Label>{i18n('label.read-only')}</Label>
18+
</Flex>
19+
);
20+
}
21+
22+
return entityName;
23+
}

src/containers/Tenant/ObjectSummary/ObjectSummary.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import type {InfoViewerItem} from '../../../components/InfoViewer/InfoViewer';
1515
import {LinkWithIcon} from '../../../components/LinkWithIcon/LinkWithIcon';
1616
import {Loader} from '../../../components/Loader';
1717
import SplitPane from '../../../components/SplitPane';
18-
import {getEntityName} from '../../../containers/Tenant/utils';
1918
import routes, {createExternalUILink, createHref} from '../../../routes';
2019
import {schemaApi, setShowPreview} from '../../../store/reducers/schema/schema';
2120
import {
@@ -33,6 +32,7 @@ import {
3332
import {formatDateTime, formatSecondsToHours} from '../../../utils/dataFormatters/dataFormatters';
3433
import {useTypedDispatch, useTypedSelector} from '../../../utils/hooks';
3534
import {Acl} from '../Acl/Acl';
35+
import {EntityTitle} from '../EntityTitle/EntityTitle';
3636
import {SchemaTree} from '../Schema/SchemaTree/SchemaTree';
3737
import {SchemaViewer} from '../Schema/SchemaViewer/SchemaViewer';
3838
import {TENANT_INFO_TABS, TENANT_SCHEMA_TAB, TenantTabsGroups} from '../TenantPages';
@@ -159,7 +159,8 @@ export function ObjectSummary({
159159
});
160160

161161
const {PathDescription} = currentObjectData;
162-
const title = getEntityName(PathDescription);
162+
163+
const title = <EntityTitle data={PathDescription} />;
163164

164165
const getPathTypeOverview: Record<EPathType, (() => InfoViewerItem[]) | undefined> = {
165166
[EPathType.EPathTypeInvalid]: undefined,

src/containers/Tenant/i18n/en.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"summary.mode": "Mode",
2222
"summary.format": "Format",
2323
"summary.retention": "Retention",
24+
"label.read-only": "ReadOnly",
2425
"actions.copied": "The path is copied to the clipboard",
2526
"actions.notCopied": "Couldn’t copy the path",
2627
"actions.copyPath": "Copy path",

src/containers/Tenant/utils/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,9 @@ export const getEntityName = (pathDescription?: TPathDescription) => {
77

88
return mapPathTypeToEntityName(PathType, PathSubType);
99
};
10+
11+
export const isReadOnlyTable = (pathDescription?: TPathDescription) => {
12+
return pathDescription?.UserAttributes?.some(({Key, Value}) => {
13+
return Key === '__async_replica' && Value === 'true';
14+
});
15+
};

src/types/api/schema/schema.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ export interface TPathDescription {
6161
/** info about the path itself */
6262
Self?: TDirEntry;
6363
DomainDescription?: TDomainDescription;
64+
UserAttributes?: TUserAttribute[];
6465

6566
// for directory
6667
Children?: TDirEntry[];
@@ -309,3 +310,8 @@ interface TTablePartition {
309310
/** uint64 */
310311
DatashardId?: string;
311312
}
313+
314+
interface TUserAttribute {
315+
Key?: string;
316+
Value?: string;
317+
}

0 commit comments

Comments
 (0)