Skip to content
Open
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
c69e19e
feat: support additional table index types
kkdras Jul 19, 2026
e58bed0
feat: add common info for schema objects
kkdras Jul 19, 2026
d64612c
refactor: extract reusable view code block
kkdras Jul 19, 2026
a09cdba
fix: restore path version copy action
kkdras Jul 19, 2026
15d5c6b
test: update object summary navigation expectations
kkdras Jul 19, 2026
a2a8ffc
test: update table index info snapshots
kkdras Jul 20, 2026
827767c
fix: show schema object metadata for all users
kkdras Jul 20, 2026
3de1472
test: cover schema metadata for non-admin users
kkdras Jul 20, 2026
4b9fc89
fix: align schema object info metadata
kkdras Jul 20, 2026
5b02a83
refactor: reuse query text preview in info tabs
kkdras Jul 21, 2026
8dfad5b
fix: add bloom index helpmarks
kkdras Jul 21, 2026
04a18e2
fix: refine schema object info
kkdras Jul 21, 2026
1483992
refactor: reuse label with help mark
kkdras Jul 21, 2026
7222fc3
fix: omit unavailable schema creation time
kkdras Jul 22, 2026
0712998
fix: remove redundant schema info empty states
kkdras Jul 22, 2026
2d7eeee
refactor: centralize tenant overview labels
kkdras Jul 22, 2026
caad5a8
fix: handle empty schema metadata values
kkdras Jul 22, 2026
e932a03
fix: align schema object info layout
kkdras Jul 23, 2026
8e0a081
fix: preserve streaming query info fallback
kkdras Jul 23, 2026
cc05c84
fix: handle streaming query loading fallback
kkdras Jul 24, 2026
f11fdf9
fix: omit unavailable schema info fields
kkdras Jul 24, 2026
bc97305
test: update streaming query info snapshot
kkdras Jul 24, 2026
926dd2f
fix: restrict schema metadata to administrators
kkdras Jul 24, 2026
c845aaa
fix: omit empty schema info rows
kkdras Jul 24, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/components/InfoViewer/InfoViewer.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@
--ydb-info-viewer-font-size: var(--g-text-body-2-font-size);
--ydb-info-viewer-line-height: var(--g-text-body-2-line-height);
--ydb-info-viewer-title-font-weight: 600;
--ydb-info-viewer-title-margin: 15px 0 10px;
--ydb-info-viewer-items-gap: 7px;

font-size: var(--ydb-info-viewer-font-size);
line-height: var(--ydb-info-viewer-line-height);

&__title {
margin: var(--ydb-info-viewer-title-margin);
margin: var(--ydb-info-viewer-title-margin, 15px 0 10px);

font-weight: var(--ydb-info-viewer-title-font-weight);
}
Expand Down
29 changes: 12 additions & 17 deletions src/components/InfoViewer/schemaInfo/TableIndexInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,7 @@ import type {TEvDescribeSchemeResult} from '../../../types/api/schema';
import {cn} from '../../../utils/cn';

import i18n from './i18n';
import {
buildFulltextIndexSettingsInfo,
buildIndexInfo,
buildVectorIndexSettingsInfo,
} from './utils';
import {buildFulltextIndexSettingsInfo, buildVectorIndexSettingsInfo} from './utils';

const b = cn('ydb-diagnostics-table-info');

Expand All @@ -26,33 +22,32 @@ export const TableIndexInfo = ({data}: TableIndexInfoProps) => {
}

const TableIndex = data.PathDescription?.TableIndex;
const info: Array<InfoViewerItem> = buildIndexInfo(TableIndex);

let settings: Array<InfoViewerItem> = [];
if (TableIndex?.Type === EIndexType.EIndexTypeGlobalVectorKmeansTree) {
settings = buildVectorIndexSettingsInfo(
TableIndex?.VectorIndexKmeansTreeDescription?.Settings,
);
}
if (TableIndex?.Type === EIndexType.EIndexTypeGlobalFulltext) {
if (
TableIndex?.Type === EIndexType.EIndexTypeGlobalFulltext ||
TableIndex?.Type === EIndexType.EIndexTypeGlobalFulltextPlain ||
TableIndex?.Type === EIndexType.EIndexTypeGlobalFulltextRelevance
) {
settings = buildFulltextIndexSettingsInfo(TableIndex?.FulltextIndexDescription?.Settings);
}

if (!settings.length) {
return null;
}

return (
<div className={b()}>
<InfoViewer
info={info}
title={entityName}
info={settings}
title={i18n('title_index-settings')}
className={b('info-block')}
renderEmptyState={() => <div className={b('title')}>{entityName}</div>}
/>
{settings && settings.length ? (
<InfoViewer
info={settings}
title={i18n('title_index-settings')}
className={b('info-block')}
/>
) : null}
</div>
);
};
10 changes: 10 additions & 0 deletions src/components/InfoViewer/schemaInfo/i18n/en.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
{
"title_index-settings": "Index Settings",

"description_subtype_global": "Synchronous index is updated simultaneously with the indexed table and provides strict consistency.",
"description_subtype_global-async": "Asynchronous index receives table changes in the background and provides eventual consistency.",
"description_subtype_global-unique": "Unique secondary index enforces uniqueness for the indexed columns and is updated synchronously.",
"description_subtype_fulltext": "Full-text index enables text search by words, phrases, and, with n-grams, substrings.",
"description_subtype_fulltext-plain": "Plain full-text index stores only the inverted index and supports filtering without relevance ranking.",
"description_subtype_fulltext-relevance": "Relevance full-text index stores term frequency statistics required for relevance ranking.",
"description_subtype_vector": "Vector index enables vector search using distance or similarity functions.",
"description_subtype_local-bloom-filter": "Local bloom_filter index skips data fragments that cannot contain an exact value for equality and IN predicates.",
"description_subtype_local-bloom-ngram-filter": "Local bloom_ngram_filter index skips data fragments that cannot contain a substring for LIKE predicates.",
"description_subtype_local-min-max": "Local min_max index stores minimum and maximum values for each chunk (portion) of a column table, allowing chunks that cannot match query filters to be skipped.",
"field_clusters": "Clusters",
"field_overlap_clusters": "Overlap Clusters",
"field_levels": "Levels",
Expand Down
1 change: 1 addition & 0 deletions src/components/InfoViewer/schemaInfo/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './TableIndexInfo';
export {buildTableIndexOverviewInfo} from './utils';
Original file line number Diff line number Diff line change
@@ -1,37 +1,55 @@
import tenantKeyset from '../../../containers/Tenant/i18n';
import type {TIndexDescription} from '../../../types/api/schema';
import {EIndexType} from '../../../types/api/schema';
import type {
TFulltextIndexAnalyzers,
TFulltextIndexSettings,
TKMeansTreeSettings,
TVectorIndexSettings,
} from '../../../types/api/schema/tableIndex';
import {formatNumber} from '../../../utils/dataFormatters/dataFormatters';
import {SchemaObjectTypeLabel} from '../../SchemaObjectTypeLabel/SchemaObjectTypeLabel';
import type {YDBDefinitionListItem} from '../../YDBDefinitionList/YDBDefinitionList';
import type {InfoViewerItem} from '../InfoViewer';
import {formatTableIndexItem} from '../formatters';
import {createInfoFormatter} from '../utils';

import i18n from './i18n';

const DISPLAYED_FIELDS_KEYS = [
'Type',
const INDEX_DETAILS_FIELDS_KEYS = [
'State',
'DataSize',
'KeyColumnNames',
'DataColumnNames',
] as const;
type DisplayedIndexField = (typeof DISPLAYED_FIELDS_KEYS)[number];
type IndexDetailsField = (typeof INDEX_DETAILS_FIELDS_KEYS)[number];

export function getDisplayedIndexFields(): ReadonlySet<DisplayedIndexField> {
return new Set<DisplayedIndexField>(DISPLAYED_FIELDS_KEYS);
}
const INDEX_TYPE_DESCRIPTIONS: Record<EIndexType, string | undefined> = {
[EIndexType.EIndexTypeInvalid]: undefined,
[EIndexType.EIndexTypeGlobal]: i18n('description_subtype_global'),
[EIndexType.EIndexTypeGlobalAsync]: i18n('description_subtype_global-async'),
[EIndexType.EIndexTypeGlobalUnique]: i18n('description_subtype_global-unique'),
[EIndexType.EIndexTypeGlobalVectorKmeansTree]: i18n('description_subtype_vector'),
[EIndexType.EIndexTypeGlobalFulltext]: i18n('description_subtype_fulltext'),
[EIndexType.EIndexTypeGlobalFulltextPlain]: i18n('description_subtype_fulltext-plain'),
[EIndexType.EIndexTypeGlobalFulltextRelevance]: i18n('description_subtype_fulltext-relevance'),
[EIndexType.EIndexTypeLocalBloomFilter]: i18n('description_subtype_local-bloom-filter'),
[EIndexType.EIndexTypeLocalBloomNgramFilter]: i18n(
'description_subtype_local-bloom-ngram-filter',
),
[EIndexType.EIndexTypeLocalMinMax]: i18n('description_subtype_local-min-max'),
};

export function buildIndexInfo(tableIndex?: TIndexDescription): InfoViewerItem[] {
function buildIndexInfoForFields(
tableIndex: TIndexDescription | undefined,
fields: readonly IndexDetailsField[],
): InfoViewerItem[] {
const info: InfoViewerItem[] = [];
if (!tableIndex) {
return info;
}

getDisplayedIndexFields().forEach((key) => {
fields.forEach((key) => {
const value = tableIndex[key];
if (value !== undefined) {
info.push(formatTableIndexItem(key, value));
Expand All @@ -41,6 +59,37 @@ export function buildIndexInfo(tableIndex?: TIndexDescription): InfoViewerItem[]
return info;
}

function toDefinitionListItem({label, value}: InfoViewerItem): YDBDefinitionListItem {
return {
name: String(label),
content: value,
};
}

export function buildTableIndexOverviewInfo(tableIndex?: TIndexDescription) {
const type = tableIndex?.Type;
const itemsAfterType: YDBDefinitionListItem[] = [];

if (type !== undefined) {
const typeItem = formatTableIndexItem('Type', type);
itemsAfterType.push({
name: tenantKeyset('summary.subtype'),
content: (
<SchemaObjectTypeLabel
value={typeItem.value}
description={INDEX_TYPE_DESCRIPTIONS[type]}
/>
),
});
}

const additionalItems = buildIndexInfoForFields(tableIndex, INDEX_DETAILS_FIELDS_KEYS).map(
toDefinitionListItem,
);

return {itemsAfterType, additionalItems};
}

/* eslint-disable camelcase */

export function buildVectorIndexSettingsInfo(
Expand Down
24 changes: 1 addition & 23 deletions src/components/QueryDetails/QueryDetails.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
@use '../../styles/mixins.scss';

.ydb-query-details {
--g-definition-list-item-gap: var(--g-spacing-2);
flex: 1;
Expand All @@ -14,35 +12,15 @@
padding: var(--g-spacing-5) var(--g-spacing-4) var(--g-spacing-5) var(--g-spacing-4);
}

&__query-header {
display: flex;
justify-content: space-between;
align-items: center;

padding: var(--g-spacing-2) var(--g-spacing-3);

border-bottom: 1px solid var(--g-color-line-generic);
}

&__query-title {
font-size: 14px;
font-weight: 500;
}

&__query-details-info {
flex-grow: 0;
}

&__query-content {
position: relative;
--ydb-syntax-highlighter-height: 100%;

display: flex;
flex: 1;
flex-direction: column;

margin-top: var(--g-spacing-5);

border-radius: 4px;
background-color: var(--code-background-color);
}
}
41 changes: 20 additions & 21 deletions src/components/QueryDetails/QueryDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {Code} from '@gravity-ui/icons';
import {Button, Flex, Icon} from '@gravity-ui/uikit';

import {cn} from '../../utils/cn';
import {YDBSyntaxHighlighter} from '../SyntaxHighlighter/YDBSyntaxHighlighter';
import {QueryTextPreview} from '../QueryTextPreview/QueryTextPreview';
import type {YDBDefinitionListItem} from '../YDBDefinitionList/YDBDefinitionList';
import {YDBDefinitionList} from '../YDBDefinitionList/YDBDefinitionList';

Expand All @@ -15,7 +15,7 @@ const b = cn('ydb-query-details');
interface QueryDetailsProps {
queryText: string;
infoItems?: YDBDefinitionListItem[];
onOpenInEditor: () => void;
onOpenInEditor?: () => void;
}

export const QueryDetails = ({queryText, infoItems, onOpenInEditor}: QueryDetailsProps) => {
Expand All @@ -29,25 +29,24 @@ export const QueryDetails = ({queryText, infoItems, onOpenInEditor}: QueryDetail
/>
)}

<div className={b('query-content')}>
<div className={b('query-header')}>
<div className={b('query-title')}>{i18n('title_query-details')}</div>
<Button
view="flat-secondary"
size="m"
onClick={onOpenInEditor}
className={b('editor-button')}
>
<Icon data={Code} size={16} />
{i18n('action_open-in-editor')}
</Button>
</div>
<YDBSyntaxHighlighter
language="yql"
text={queryText}
withClipboardButton={{alwaysVisible: true, withLabel: false, size: 'm'}}
/>
</div>
<QueryTextPreview
className={b('query-content')}
title={i18n('title_query-details')}
text={queryText}
actions={
onOpenInEditor ? (
<Button
view="flat-secondary"
size="m"
onClick={onOpenInEditor}
className={b('editor-button')}
>
<Icon data={Code} size={16} />
{i18n('action_open-in-editor')}
</Button>
) : undefined
}
/>
</Flex>
</Flex>
);
Expand Down
26 changes: 26 additions & 0 deletions src/components/QueryTextPreview/QueryTextPreview.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
.ydb-query-text-preview {
--ydb-syntax-highlighter-height: auto;

position: relative;

display: flex;
flex-direction: column;

border-radius: 4px;
background-color: var(--code-background-color);

&__header {
display: flex;
justify-content: space-between;
align-items: center;

padding: var(--g-spacing-2) var(--g-spacing-3);

border-bottom: 1px solid var(--g-color-line-generic);
}

&__title {
font-size: 14px;
font-weight: 500;
}
}
31 changes: 31 additions & 0 deletions src/components/QueryTextPreview/QueryTextPreview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React from 'react';

import {cn} from '../../utils/cn';
import {YDBSyntaxHighlighter} from '../SyntaxHighlighter/YDBSyntaxHighlighter';

import './QueryTextPreview.scss';

const b = cn('ydb-query-text-preview');

interface QueryTextPreviewProps {
text: string;
title: React.ReactNode;
actions?: React.ReactNode;
className?: string;
}

export function QueryTextPreview({text, title, actions, className}: QueryTextPreviewProps) {
return (
<div className={b(null, className)}>
<div className={b('header')}>
<div className={b('title')}>{title}</div>
{actions}
</div>
<YDBSyntaxHighlighter
language="yql"
text={text}
withClipboardButton={{alwaysVisible: true, withLabel: false, size: 'm'}}
/>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.ydb-schema-object-type-label {
&__help-mark {
color: var(--g-color-text-misc-heavy);
}

&__description {
max-width: 360px;
}
}
Loading
Loading