Skip to content

Commit 4afa2b6

Browse files
authored
feat(ObjectSummary): improve object overview (#1447)
1 parent d7a8e0b commit 4afa2b6

File tree

2 files changed

+66
-44
lines changed

2 files changed

+66
-44
lines changed

src/containers/Tenant/ObjectSummary/ObjectSummary.scss

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,4 +144,11 @@
144144
background-color: transparent;
145145
}
146146
}
147+
&__overview-title {
148+
@include info-viewer-title();
149+
}
150+
&__overview-item-content {
151+
text-align: end;
152+
white-space: nowrap;
153+
}
147154
}

src/containers/Tenant/ObjectSummary/ObjectSummary.tsx

Lines changed: 59 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React from 'react';
22

3-
import {HelpPopover} from '@gravity-ui/components';
3+
import {DefinitionList, HelpPopover} from '@gravity-ui/components';
4+
import type {DefinitionListSingleItem} from '@gravity-ui/components/build/esm/components/DefinitionList/types';
45
import {Flex, Tabs} from '@gravity-ui/uikit';
56
import qs from 'qs';
67
import {Link, useLocation} from 'react-router-dom';
@@ -9,8 +10,6 @@ import {StringParam, useQueryParam} from 'use-query-params';
910
import {AsyncReplicationState} from '../../../components/AsyncReplicationState';
1011
import {ClipboardButton} from '../../../components/ClipboardButton';
1112
import {toFormattedSize} from '../../../components/FormattedBytes/utils';
12-
import {InfoViewer} from '../../../components/InfoViewer/InfoViewer';
13-
import type {InfoViewerItem} from '../../../components/InfoViewer/InfoViewer';
1413
import {LinkWithIcon} from '../../../components/LinkWithIcon/LinkWithIcon';
1514
import SplitPane from '../../../components/SplitPane';
1615
import routes, {createExternalUILink, createHref} from '../../../routes';
@@ -156,28 +155,28 @@ export function ObjectSummary({
156155
}
157156
const {CreateStep, PathType, PathSubType, PathId, PathVersion} = currentSchemaData;
158157

159-
const overview: InfoViewerItem[] = [];
158+
const overview: DefinitionListSingleItem[] = [];
160159

161160
const normalizedType = isDomain(path, PathType)
162161
? 'Domain'
163162
: PathType?.replace(/^EPathType/, '');
164163

165-
overview.push({label: i18n('field_type'), value: normalizedType});
164+
overview.push({name: i18n('field_type'), content: normalizedType});
166165

167166
if (PathSubType !== EPathSubType.EPathSubTypeEmpty) {
168167
overview.push({
169-
label: i18n('field_subtype'),
170-
value: PathSubType?.replace(/^EPathSubType/, ''),
168+
name: i18n('field_subtype'),
169+
content: PathSubType?.replace(/^EPathSubType/, ''),
171170
});
172171
}
173172

174-
overview.push({label: i18n('field_id'), value: PathId});
173+
overview.push({name: i18n('field_id'), content: PathId});
175174

176-
overview.push({label: i18n('field_version'), value: PathVersion});
175+
overview.push({name: i18n('field_version'), content: PathVersion});
177176

178177
overview.push({
179-
label: i18n('field_created'),
180-
value: formatDateTime(CreateStep),
178+
name: i18n('field_created'),
179+
content: formatDateTime(CreateStep),
181180
});
182181

183182
const {PathDescription} = currentObjectData;
@@ -187,18 +186,16 @@ export function ObjectSummary({
187186

188187
overview.push(
189188
{
190-
label: i18n('field_data-size'),
191-
value: toFormattedSize(DataSize),
189+
name: i18n('field_data-size'),
190+
content: toFormattedSize(DataSize),
192191
},
193192
{
194-
label: i18n('field_row-count'),
195-
value: formatNumber(RowCount),
193+
name: i18n('field_row-count'),
194+
content: formatNumber(RowCount),
196195
},
197196
);
198197
}
199198

200-
const title = <EntityTitle data={PathDescription} />;
201-
202199
const getDatabaseOverview = () => {
203200
const {PathsInside, ShardsInside, PathsLimit, ShardsLimit} =
204201
PathDescription?.DomainDescription ?? {};
@@ -215,51 +212,55 @@ export function ObjectSummary({
215212

216213
return [
217214
{
218-
label: i18n('field_paths'),
219-
value: paths,
215+
name: i18n('field_paths'),
216+
content: paths,
220217
},
221218
{
222-
label: i18n('field_shards'),
223-
value: shards,
219+
name: i18n('field_shards'),
220+
content: shards,
224221
},
225222
];
226223
};
227224

228-
const getPathTypeOverview: Record<EPathType, (() => InfoViewerItem[]) | undefined> = {
225+
const getPathTypeOverview: Record<
226+
EPathType,
227+
(() => DefinitionListSingleItem[]) | undefined
228+
> = {
229229
[EPathType.EPathTypeInvalid]: undefined,
230230
[EPathType.EPathTypeDir]: undefined,
231231
[EPathType.EPathTypeTable]: () => [
232232
{
233-
label: i18n('field_partitions'),
234-
value: PathDescription?.TablePartitions?.length,
233+
name: i18n('field_partitions'),
234+
content: PathDescription?.TablePartitions?.length,
235235
},
236236
],
237237
[EPathType.EPathTypeSubDomain]: getDatabaseOverview,
238238
[EPathType.EPathTypeTableIndex]: undefined,
239239
[EPathType.EPathTypeExtSubDomain]: getDatabaseOverview,
240240
[EPathType.EPathTypeColumnStore]: () => [
241241
{
242-
label: i18n('field_partitions'),
243-
value: PathDescription?.ColumnStoreDescription?.ColumnShards?.length,
242+
name: i18n('field_partitions'),
243+
content: PathDescription?.ColumnStoreDescription?.ColumnShards?.length,
244244
},
245245
],
246246
[EPathType.EPathTypeColumnTable]: () => [
247247
{
248-
label: i18n('field_partitions'),
249-
value: PathDescription?.ColumnTableDescription?.Sharding?.ColumnShards?.length,
248+
name: i18n('field_partitions'),
249+
content:
250+
PathDescription?.ColumnTableDescription?.Sharding?.ColumnShards?.length,
250251
},
251252
],
252253
[EPathType.EPathTypeCdcStream]: () => {
253254
const {Mode, Format} = PathDescription?.CdcStreamDescription || {};
254255

255256
return [
256257
{
257-
label: i18n('field_mode'),
258-
value: Mode?.replace(/^ECdcStreamMode/, ''),
258+
name: i18n('field_mode'),
259+
content: Mode?.replace(/^ECdcStreamMode/, ''),
259260
},
260261
{
261-
label: i18n('field_format'),
262-
value: Format?.replace(/^ECdcStreamFormat/, ''),
262+
name: i18n('field_format'),
263+
content: Format?.replace(/^ECdcStreamFormat/, ''),
263264
},
264265
];
265266
},
@@ -269,12 +270,12 @@ export function ObjectSummary({
269270

270271
return [
271272
{
272-
label: i18n('field_partitions'),
273-
value: pqGroup?.Partitions?.length,
273+
name: i18n('field_partitions'),
274+
content: pqGroup?.Partitions?.length,
274275
},
275276
{
276-
label: i18n('field_retention'),
277-
value: value && formatSecondsToHours(value),
277+
name: i18n('field_retention'),
278+
content: value && formatSecondsToHours(value),
278279
},
279280
];
280281
},
@@ -290,10 +291,10 @@ export function ObjectSummary({
290291
const dataSourceName = DataSourcePath?.match(/([^/]*)\/*$/)?.[1] || '';
291292

292293
return [
293-
{label: i18n('field_source-type'), value: SourceType},
294+
{name: i18n('field_source-type'), content: SourceType},
294295
{
295-
label: i18n('field_data-source'),
296-
value: DataSourcePath && (
296+
name: i18n('field_data-source'),
297+
content: DataSourcePath && (
297298
<span title={DataSourcePath}>
298299
<LinkWithIcon title={dataSourceName || ''} url={pathToDataSource} />
299300
</span>
@@ -303,8 +304,8 @@ export function ObjectSummary({
303304
},
304305
[EPathType.EPathTypeExternalDataSource]: () => [
305306
{
306-
label: i18n('field_source-type'),
307-
value: PathDescription?.ExternalDataSourceDescription?.SourceType,
307+
name: i18n('field_source-type'),
308+
content: PathDescription?.ExternalDataSourceDescription?.SourceType,
308309
},
309310
],
310311
[EPathType.EPathTypeView]: undefined,
@@ -317,8 +318,8 @@ export function ObjectSummary({
317318

318319
return [
319320
{
320-
label: i18n('field_state'),
321-
value: <AsyncReplicationState state={state} />,
321+
name: i18n('field_state'),
322+
content: <AsyncReplicationState state={state} />,
322323
},
323324
];
324325
},
@@ -329,7 +330,21 @@ export function ObjectSummary({
329330

330331
// filter all empty values in according this requirement
331332
// https://github.com/ydb-platform/ydb-embedded-ui/issues/906
332-
return <InfoViewer title={title} info={overview.filter((i) => i.value)} />;
333+
const listItems = overview
334+
.filter((i) => i.content)
335+
.map((el) => ({
336+
...el,
337+
content: <div className={b('overview-item-content')}>{el.content}</div>,
338+
multilineName: true,
339+
}));
340+
return (
341+
<React.Fragment>
342+
<div className={b('overview-title')}>
343+
<EntityTitle data={PathDescription} />
344+
</div>
345+
<DefinitionList items={listItems} responsive nameMaxWidth={150} />
346+
</React.Fragment>
347+
);
333348
};
334349

335350
const renderTabContent = () => {

0 commit comments

Comments
 (0)