diff --git a/src/components/InfoViewer/formatters/schema.ts b/src/components/InfoViewer/formatters/schema.ts index 22192966a0..896031aeb1 100644 --- a/src/components/InfoViewer/formatters/schema.ts +++ b/src/components/InfoViewer/formatters/schema.ts @@ -1,5 +1,6 @@ import type {TIndexDescription} from '../../../types/api/schema'; import {toFormattedSize} from '../../FormattedBytes/utils'; +import i18n from '../schemaInfo/i18n'; import {createInfoFormatter} from '../utils'; export const formatTableIndexItem = createInfoFormatter({ @@ -11,7 +12,8 @@ export const formatTableIndexItem = createInfoFormatter({ DataSize: toFormattedSize, }, labels: { - KeyColumnNames: 'Columns', - DataColumnNames: 'Includes', + KeyColumnNames: i18n('field_columns'), + DataColumnNames: i18n('field_includes'), + DataSize: i18n('field_data-size'), }, }); diff --git a/src/components/InfoViewer/schemaInfo/TableIndexInfo.tsx b/src/components/InfoViewer/schemaInfo/TableIndexInfo.tsx index ba5650ce23..8a2bf771ae 100644 --- a/src/components/InfoViewer/schemaInfo/TableIndexInfo.tsx +++ b/src/components/InfoViewer/schemaInfo/TableIndexInfo.tsx @@ -1,16 +1,10 @@ import type {InfoViewerItem} from '..'; import {InfoViewer} from '..'; import {getEntityName} from '../../../containers/Tenant/utils'; -import type {TEvDescribeSchemeResult, TIndexDescription} from '../../../types/api/schema'; -import {formatTableIndexItem} from '../formatters'; +import type {TEvDescribeSchemeResult} from '../../../types/api/schema'; -const DISPLAYED_FIELDS: Set = new Set([ - 'Type', - 'State', - 'DataSize', - 'KeyColumnNames', - 'DataColumnNames', -]); +import i18n from './i18n'; +import {buildIndexInfo, buildVectorIndexInfo} from './utils'; interface TableIndexInfoProps { data?: TEvDescribeSchemeResult; @@ -20,18 +14,24 @@ export const TableIndexInfo = ({data}: TableIndexInfoProps) => { const entityName = getEntityName(data?.PathDescription); if (!data) { - return
No {entityName} data
; + return
{i18n('alert_no-entity-data', {entity: entityName})}
; } const TableIndex = data.PathDescription?.TableIndex; - const info: Array = []; + const info: Array = buildIndexInfo(TableIndex); - let key: keyof TIndexDescription; - for (key in TableIndex) { - if (DISPLAYED_FIELDS.has(key)) { - info.push(formatTableIndexItem(key, TableIndex?.[key])); - } + const vectorSettings = TableIndex?.VectorIndexKmeansTreeDescription?.Settings; + + if (!vectorSettings) { + return ; } - return ; + const vectorInfo: Array = buildVectorIndexInfo(vectorSettings); + + return ( + <> + + + + ); }; diff --git a/src/components/InfoViewer/schemaInfo/i18n/en.json b/src/components/InfoViewer/schemaInfo/i18n/en.json new file mode 100644 index 0000000000..7d7e5172d9 --- /dev/null +++ b/src/components/InfoViewer/schemaInfo/i18n/en.json @@ -0,0 +1,12 @@ +{ + "title_vector-index": "Vector Index", + "field_clusters": "Clusters", + "field_levels": "Levels", + "field_vector-dimension": "Vector Dimension", + "field_vector-type": "Vector Type", + "field_metric": "Metric", + "field_columns": "Columns", + "field_includes": "Includes", + "field_data-size": "Data Size", + "alert_no-entity-data": "No {{entity}} data" +} diff --git a/src/components/InfoViewer/schemaInfo/i18n/index.ts b/src/components/InfoViewer/schemaInfo/i18n/index.ts new file mode 100644 index 0000000000..a516b70e53 --- /dev/null +++ b/src/components/InfoViewer/schemaInfo/i18n/index.ts @@ -0,0 +1,7 @@ +import {registerKeysets} from '../../../../utils/i18n'; + +import en from './en.json'; + +const COMPONENT = 'info-viewer-schema-index-info'; + +export default registerKeysets(COMPONENT, {en}); diff --git a/src/components/InfoViewer/schemaInfo/utils.ts b/src/components/InfoViewer/schemaInfo/utils.ts new file mode 100644 index 0000000000..b765e98912 --- /dev/null +++ b/src/components/InfoViewer/schemaInfo/utils.ts @@ -0,0 +1,93 @@ +import type {TIndexDescription} from '../../../types/api/schema'; +import type { + TVectorIndexKmeansTreeDescriptionSettings, + TVectorIndexKmeansTreeDescriptionSettingsInner, +} from '../../../types/api/schema/tableIndex'; +import {formatNumber} from '../../../utils/dataFormatters/dataFormatters'; +import type {InfoViewerItem} from '../InfoViewer'; +import {formatTableIndexItem} from '../formatters'; +import {createInfoFormatter} from '../utils'; + +import i18n from './i18n'; + +const DISPLAYED_FIELDS_KEYS = [ + 'Type', + 'State', + 'DataSize', + 'KeyColumnNames', + 'DataColumnNames', +] as const; +type DisplayedIndexField = (typeof DISPLAYED_FIELDS_KEYS)[number]; + +export function getDisplayedIndexFields(): ReadonlySet { + return new Set(DISPLAYED_FIELDS_KEYS); +} + +export function buildIndexInfo(tableIndex?: TIndexDescription): InfoViewerItem[] { + const info: InfoViewerItem[] = []; + if (!tableIndex) { + return info; + } + + getDisplayedIndexFields().forEach((key) => { + const value = tableIndex[key]; + if (value !== undefined) { + info.push(formatTableIndexItem(key, value)); + } + }); + + return info; +} + +type VectorSettings = TVectorIndexKmeansTreeDescriptionSettings; + +export function buildVectorIndexInfo(vectorSettings?: VectorSettings): InfoViewerItem[] { + const info: InfoViewerItem[] = []; + if (!vectorSettings) { + return info; + } + + const vectorFormatter = createInfoFormatter>({ + values: { + clusters: (v) => (typeof v === 'number' ? formatNumber(v) : v), + levels: (v) => (typeof v === 'number' ? formatNumber(v) : v), + }, + labels: { + clusters: i18n('field_clusters'), + levels: i18n('field_levels'), + }, + }); + + const settingsFormatter = createInfoFormatter({ + values: { + vector_dimension: (v) => (typeof v === 'number' ? formatNumber(v) : v), + }, + labels: { + 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)); + } + if (levels !== undefined) { + info.push(vectorFormatter('levels', levels)); + } + + const {vector_dimension: vectorDimension, vector_type: vectorType, metric} = settings ?? {}; + + if (vectorDimension !== undefined) { + info.push(settingsFormatter('vector_dimension', vectorDimension)); + } + if (vectorType !== undefined) { + info.push(settingsFormatter('vector_type', vectorType)); + } + if (metric !== undefined) { + info.push(settingsFormatter('metric', metric)); + } + + return info; +} diff --git a/src/types/api/schema/tableIndex.ts b/src/types/api/schema/tableIndex.ts index 655c8292bc..2a6f6b56b2 100644 --- a/src/types/api/schema/tableIndex.ts +++ b/src/types/api/schema/tableIndex.ts @@ -19,12 +19,18 @@ export interface TIndexDescription { DataColumnNames?: string[]; /** uint64 */ DataSize?: string; + + /** + * Present for vector indexes of type EIndexTypeGlobalVectorKmeansTree + */ + VectorIndexKmeansTreeDescription?: TVectorIndexKmeansTreeDescription; } enum EIndexType { EIndexTypeInvalid = 'EIndexTypeInvalid', EIndexTypeGlobal = 'EIndexTypeGlobal', EIndexTypeGlobalAsync = 'EIndexTypeGlobalAsync', + EIndexTypeGlobalVectorKmeansTree = 'EIndexTypeGlobalVectorKmeansTree', } enum EIndexState { @@ -33,3 +39,19 @@ enum EIndexState { EIndexStateNotReady = 'EIndexStateNotReady', EIndexStateWriteOnly = 'EIndexStateWriteOnly', } + +export interface TVectorIndexKmeansTreeDescriptionSettingsInner { + vector_dimension?: number; + vector_type?: string; + metric?: string; +} + +export interface TVectorIndexKmeansTreeDescriptionSettings { + clusters?: number; + levels?: number; + settings?: TVectorIndexKmeansTreeDescriptionSettingsInner; +} + +export interface TVectorIndexKmeansTreeDescription { + Settings?: TVectorIndexKmeansTreeDescriptionSettings; +}