Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
45 changes: 32 additions & 13 deletions src/components/InfoViewer/schemaInfo/TableIndexInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,16 @@ import {InfoViewer} from '..';
import {getEntityName} from '../../../containers/Tenant/utils';
import {EIndexType} from '../../../types/api/schema';
import type {TEvDescribeSchemeResult} from '../../../types/api/schema';
import {cn} from '../../../utils/cn';

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

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

interface TableIndexInfoProps {
data?: TEvDescribeSchemeResult;
Expand All @@ -21,19 +28,31 @@ export const TableIndexInfo = ({data}: TableIndexInfoProps) => {
const TableIndex = data.PathDescription?.TableIndex;
const info: Array<InfoViewerItem> = buildIndexInfo(TableIndex);

const vectorSettings = TableIndex?.VectorIndexKmeansTreeDescription?.Settings;

const isVectorIndex = TableIndex?.Type === EIndexType.EIndexTypeGlobalVectorKmeansTree;

if (isVectorIndex) {
const vectorInfo: Array<InfoViewerItem> = buildVectorIndexInfo(vectorSettings);
return (
<>
<InfoViewer title={i18n('title_vector-index')} info={info} />
<InfoViewer info={vectorInfo} />
</>
let settings: Array<InfoViewerItem> = [];
if (TableIndex?.Type === EIndexType.EIndexTypeGlobalVectorKmeansTree) {
settings = buildVectorIndexSettingsInfo(
TableIndex?.VectorIndexKmeansTreeDescription?.Settings,
);
}
if (TableIndex?.Type === EIndexType.EIndexTypeGlobalFulltext) {
settings = buildFulltextIndexSettingsInfo(TableIndex?.FulltextIndexDescription?.Settings);
}

return <InfoViewer title={entityName} info={info} />;
return (
<div className={b()}>
<InfoViewer
info={info}
title={entityName}
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>
);
};
23 changes: 20 additions & 3 deletions src/components/InfoViewer/schemaInfo/i18n/en.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,29 @@
{
"title_vector-index": "Vector Index",
"title_index-settings": "Index Settings",

"field_clusters": "Clusters",
"field_levels": "Levels",
"field_vector-dimension": "Vector Dimension",
"field_vector-type": "Vector Type",
"field_vector_dimension": "Vector Dimension",
"field_vector_type": "Vector Type",
"field_metric": "Metric",
"field_columns": "Columns",
"field_includes": "Includes",
"field_data-size": "Data Size",

"field_layout": "Layout",
"field_tokenizer": "Tokenizer",
"field_language": "Language",
"field_use_filter_lowercase": "Filter Lowercase",
"field_use_filter_stopwords": "Filter Stopwords",
"field_use_filter_ngram": "Filter Ngram",
"field_use_filter_edge_ngram": "Filter Edge Ngram",
"field_filter_ngram_min_length": "Filter Ngram Min Length",
"field_filter_ngram_max_length": "Filter Ngram Max Length",
"field_use_filter_length": "Filter Length",
"field_filter_length_min": "Filter Length Min",
"field_filter_length_max": "Filter Length Max",
"filter_enabled": "Enabled",
"filter_disabled": "Disabled",

"alert_no-entity-data": "No {{entity}} data"
}
161 changes: 140 additions & 21 deletions src/components/InfoViewer/schemaInfo/utils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import type {TIndexDescription} from '../../../types/api/schema';
import type {
TVectorIndexKmeansTreeDescriptionSettings,
TVectorIndexKmeansTreeDescriptionSettingsInner,
TFulltextIndexAnalyzers,
TFulltextIndexSettings,
TKMeansTreeSettings,
TVectorIndexSettings,
} from '../../../types/api/schema/tableIndex';
import {formatNumber} from '../../../utils/dataFormatters/dataFormatters';
import type {InfoViewerItem} from '../InfoViewer';
Expand Down Expand Up @@ -39,15 +41,19 @@ export function buildIndexInfo(tableIndex?: TIndexDescription): InfoViewerItem[]
return info;
}

type VectorSettings = TVectorIndexKmeansTreeDescriptionSettings;
/* eslint-disable camelcase */

export function buildVectorIndexInfo(vectorSettings?: VectorSettings): InfoViewerItem[] {
export function buildVectorIndexSettingsInfo(
kMeansTreeSettings?: TKMeansTreeSettings,
): InfoViewerItem[] {
const info: InfoViewerItem[] = [];
if (!vectorSettings) {
if (!kMeansTreeSettings) {
return info;
}

const vectorFormatter = createInfoFormatter<Pick<VectorSettings, 'clusters' | 'levels'>>({
const kMeansTreeSettingsFormatter = createInfoFormatter<
Pick<TKMeansTreeSettings, 'clusters' | 'levels'>
>({
values: {
clusters: (v) => (typeof v === 'number' ? formatNumber(v) : v),
levels: (v) => (typeof v === 'number' ? formatNumber(v) : v),
Expand All @@ -58,37 +64,150 @@ export function buildVectorIndexInfo(vectorSettings?: VectorSettings): InfoViewe
},
});

const settingsFormatter = createInfoFormatter<TVectorIndexKmeansTreeDescriptionSettingsInner>({
const {clusters, levels, settings} = kMeansTreeSettings;
if (clusters !== undefined) {
info.push(kMeansTreeSettingsFormatter('clusters', clusters));
}
if (levels !== undefined) {
info.push(kMeansTreeSettingsFormatter('levels', levels));
}

const vectorIndexSettingsFormatter = createInfoFormatter<TVectorIndexSettings>({
values: {
vector_dimension: (v) => (typeof v === 'number' ? formatNumber(v) : v),
vector_type: (v) => (typeof v === 'string' ? v.replace(/^VECTOR_TYPE_/, '') : v),
},
labels: {
vector_dimension: i18n('field_vector-dimension'),
vector_type: i18n('field_vector-type'),
vector_dimension: i18n('field_vector_dimension'),
vector_type: i18n('field_vector_type'),
metric: i18n('field_metric'),
},
});

const {clusters, levels, settings} = vectorSettings ?? {};
if (clusters !== undefined) {
info.push(vectorFormatter('clusters', clusters));
const {metric, vector_type, vector_dimension} = settings ?? {};
if (metric !== undefined) {
info.push(vectorIndexSettingsFormatter('metric', metric));
}
if (levels !== undefined) {
info.push(vectorFormatter('levels', levels));
if (vector_type !== undefined) {
info.push(vectorIndexSettingsFormatter('vector_type', vector_type));
}
if (vector_dimension !== undefined) {
info.push(vectorIndexSettingsFormatter('vector_dimension', vector_dimension));
}

const {vector_dimension: vectorDimension, vector_type: vectorType, metric} = settings ?? {};
return info;
}

if (vectorDimension !== undefined) {
info.push(settingsFormatter('vector_dimension', vectorDimension));
export function buildFulltextIndexSettingsInfo(
fulltextSettings?: TFulltextIndexSettings,
): InfoViewerItem[] {
const info: InfoViewerItem[] = [];
if (!fulltextSettings) {
return info;
}
if (vectorType !== undefined) {
info.push(settingsFormatter('vector_type', vectorType));

const fulltextFormatter = createInfoFormatter<Pick<TFulltextIndexSettings, 'layout'>>({
values: {
layout: (v) => v,
},
labels: {
layout: i18n('field_layout'),
},
});

const {layout} = fulltextSettings;
if (layout !== undefined) {
info.push(fulltextFormatter('layout', layout));
}
if (metric !== undefined) {
info.push(settingsFormatter('metric', metric));

const fulltextIndexAnalyzersFormatter = createInfoFormatter<TFulltextIndexAnalyzers>({
values: {
tokenizer: (v) => v,
language: (v) => v,
use_filter_lowercase: (v) =>
v === true ? i18n('filter_enabled') : i18n('filter_disabled'),
use_filter_stopwords: (v) =>
v === true ? i18n('filter_enabled') : i18n('filter_disabled'),
use_filter_ngram: (v) =>
v === true ? i18n('filter_enabled') : i18n('filter_disabled'),
use_filter_edge_ngram: (v) =>
v === true ? i18n('filter_enabled') : i18n('filter_disabled'),
filter_ngram_min_length: (v) => (typeof v === 'number' ? formatNumber(v) : v),
filter_ngram_max_length: (v) => (typeof v === 'number' ? formatNumber(v) : v),
use_filter_length: (v) =>
v === true ? i18n('filter_enabled') : i18n('filter_disabled'),
filter_length_min: (v) => (typeof v === 'number' ? formatNumber(v) : v),
filter_length_max: (v) => (typeof v === 'number' ? formatNumber(v) : v),
},
labels: {
tokenizer: i18n('field_tokenizer'),
language: i18n('field_language'),
use_filter_lowercase: i18n('field_use_filter_lowercase'),
use_filter_stopwords: i18n('field_use_filter_stopwords'),
use_filter_ngram: i18n('field_use_filter_ngram'),
use_filter_edge_ngram: i18n('field_use_filter_edge_ngram'),
filter_ngram_min_length: i18n('field_filter_ngram_min_length'),
filter_ngram_max_length: i18n('field_filter_ngram_max_length'),
use_filter_length: i18n('field_use_filter_length'),
filter_length_min: i18n('field_filter_length_min'),
filter_length_max: i18n('field_filter_length_max'),
},
});

const analyzers = fulltextSettings.columns?.filter((col) => col.analyzers !== undefined)[0]
?.analyzers;
const {
tokenizer,
language,
use_filter_lowercase,
use_filter_stopwords,
use_filter_ngram,
use_filter_edge_ngram,
filter_ngram_min_length,
filter_ngram_max_length,
use_filter_length,
filter_length_min,
filter_length_max,
} = analyzers ?? {};
if (tokenizer !== undefined) {
info.push(fulltextIndexAnalyzersFormatter('tokenizer', tokenizer));
}
if (language !== undefined) {
info.push(fulltextIndexAnalyzersFormatter('language', language));
}
if (use_filter_lowercase !== undefined) {
info.push(fulltextIndexAnalyzersFormatter('use_filter_lowercase', use_filter_lowercase));
}
if (use_filter_stopwords !== undefined) {
info.push(fulltextIndexAnalyzersFormatter('use_filter_stopwords', use_filter_stopwords));
}
if (use_filter_ngram !== undefined) {
info.push(fulltextIndexAnalyzersFormatter('use_filter_ngram', use_filter_ngram));
}
if (use_filter_edge_ngram !== undefined) {
info.push(fulltextIndexAnalyzersFormatter('use_filter_edge_ngram', use_filter_edge_ngram));
}
if (filter_ngram_min_length !== undefined) {
info.push(
fulltextIndexAnalyzersFormatter('filter_ngram_min_length', filter_ngram_min_length),
);
}
if (filter_ngram_max_length !== undefined) {
info.push(
fulltextIndexAnalyzersFormatter('filter_ngram_max_length', filter_ngram_max_length),
);
}
if (use_filter_length !== undefined) {
info.push(fulltextIndexAnalyzersFormatter('use_filter_length', use_filter_length));
}
if (filter_length_min !== undefined) {
info.push(fulltextIndexAnalyzersFormatter('filter_length_min', filter_length_min));
}
if (filter_length_max !== undefined) {
info.push(fulltextIndexAnalyzersFormatter('filter_length_max', filter_length_max));
}

return info;
}

/* eslint-enable camelcase */
2 changes: 2 additions & 0 deletions src/containers/Tenant/Diagnostics/DiagnosticsPages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,8 @@ const pathSubTypeToPages: Record<EPathSubType, Page[] | undefined> = {

[EPathSubType.EPathSubTypeSyncIndexImplTable]: undefined,
[EPathSubType.EPathSubTypeAsyncIndexImplTable]: undefined,
[EPathSubType.EPathSubTypeVectorKmeansTreeIndexImplTable]: undefined,
[EPathSubType.EPathSubTypeFulltextIndexImplTable]: undefined,
[EPathSubType.EPathSubTypeEmpty]: undefined,
};

Expand Down
6 changes: 3 additions & 3 deletions src/containers/Tenant/ObjectSummary/ObjectSummary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ import {
PaneVisibilityToggleButtons,
paneVisibilityToggleReducerCreator,
} from '../utils/paneVisibilityToggleHelpers';
import {isIndexTableType, isTableType} from '../utils/schema';
import {isTableType} from '../utils/schema';

import {ObjectTree} from './ObjectTree';
import {SchemaActions} from './SchemaActions';
Expand Down Expand Up @@ -77,7 +77,7 @@ export function ObjectSummary({
onExpandSummary,
isCollapsed,
}: ObjectSummaryProps) {
const {path, database, type, subType, databaseFullPath} = useCurrentSchema();
const {path, database, type, databaseFullPath} = useCurrentSchema();

const dispatch = useTypedDispatch();
const {handleSchemaChange} = useTenantQueryParams();
Expand Down Expand Up @@ -404,7 +404,7 @@ export function ObjectSummary({
const relativePath = transformPath(path, databaseFullPath);

const renderCommonInfoControls = () => {
const showPreview = isTableType(type) && !isIndexTableType(subType);
const showPreview = isTableType(type);
return (
<React.Fragment>
{showPreview &&
Expand Down
6 changes: 5 additions & 1 deletion src/containers/Tenant/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@
"entity-name_table": "Table",
"entity-name_system-view": "System view",
"entity-name_secondary-index": "Secondary Index",
"entity-name_vector-index": "Vector Index",
"entity-name_fulltext-index": "Fulltext Index",
"entity-name_tablestore": "Tablestore",
"entity-name_column-oriented-table": "Column-oriented table",
"entity-name_changefeed": "Changefeed",
Expand All @@ -85,5 +87,7 @@
"entity-name_async-replication": "Async Replication",
"entity-name_transfer": "Transfer",
"entity-name_resource-pool": "Resource Pool",
"entity-name_secondary-index-table": "Secondary Index Table"
"entity-name_secondary-index-table": "Secondary Index Table",
"entity-name_vector-index-table": "Vector Index Table",
"entity-name_fulltext-index-table": "Fulltext Index Table"
}
2 changes: 1 addition & 1 deletion src/containers/Tenant/utils/controls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export const getSchemaControls =
column_table: openPreview,
system_table: openPreview,

index_table: undefined,
index_table: openPreview,
topic: isTopicPreviewAvailable && !isCdcTopic ? openPreview : undefined,
stream: undefined,

Expand Down
7 changes: 6 additions & 1 deletion src/containers/Tenant/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import {EPathType} from '../../../types/api/schema';
import type {TPathDescription} from '../../../types/api/schema';

import {mapPathTypeToEntityName} from './schema';
import {mapIndexTypeToEntityName, mapPathTypeToEntityName} from './schema';

export const getEntityName = (pathDescription?: TPathDescription) => {
const {PathType, PathSubType} = pathDescription?.Self || {};

if (PathType === EPathType.EPathTypeTableIndex) {
return mapIndexTypeToEntityName(pathDescription?.TableIndex?.Type);
}

return mapPathTypeToEntityName(PathType, PathSubType);
};

Expand Down
Loading
Loading