@@ -6,7 +6,7 @@ import {ActionTooltip, Flex, Icon, Text} from '@gravity-ui/uikit';
66import { ButtonWithConfirmDialog } from '../../components/ButtonWithConfirmDialog/ButtonWithConfirmDialog' ;
77import { CellWithPopover } from '../../components/CellWithPopover/CellWithPopover' ;
88import { operationsApi } from '../../store/reducers/operations' ;
9- import type { TOperation } from '../../types/api/operations' ;
9+ import type { IndexBuildMetadata , OperationKind , TOperation } from '../../types/api/operations' ;
1010import { EStatusCode } from '../../types/api/operations' ;
1111import { EMPTY_DATA_PLACEHOLDER , HOUR_IN_SECONDS , SECOND_IN_MS } from '../../utils/constants' ;
1212import createToast from '../../utils/createToast' ;
@@ -21,11 +21,23 @@ import './Operations.scss';
2121export function getColumns ( {
2222 database,
2323 refreshTable,
24+ kind,
2425} : {
2526 database : string ;
2627 refreshTable : VoidFunction ;
28+ kind : OperationKind ;
2729} ) : DataTableColumn < TOperation > [ ] {
28- return [
30+ const isBuildIndex = kind === 'buildindex' ;
31+
32+ // Helper function to get description tooltip content
33+ const getDescriptionTooltip = ( operation : TOperation ) : string => {
34+ if ( ! operation . metadata ?. description ) {
35+ return '' ;
36+ }
37+ return JSON . stringify ( operation . metadata . description , null , 2 ) ;
38+ } ;
39+
40+ const columns : DataTableColumn < TOperation > [ ] = [
2941 {
3042 name : COLUMNS_NAMES . ID ,
3143 header : COLUMNS_TITLES [ COLUMNS_NAMES . ID ] ,
@@ -34,8 +46,11 @@ export function getColumns({
3446 if ( ! row . id ) {
3547 return EMPTY_DATA_PLACEHOLDER ;
3648 }
49+
50+ const tooltipContent = isBuildIndex ? getDescriptionTooltip ( row ) || row . id : row . id ;
51+
3752 return (
38- < CellWithPopover placement = { [ 'top' , 'bottom' ] } content = { row . id } >
53+ < CellWithPopover placement = { [ 'top' , 'bottom' ] } content = { tooltipContent } >
3954 { row . id }
4055 </ CellWithPopover >
4156 ) ;
@@ -55,78 +70,114 @@ export function getColumns({
5570 ) ;
5671 } ,
5772 } ,
58- {
59- name : COLUMNS_NAMES . CREATED_BY ,
60- header : COLUMNS_TITLES [ COLUMNS_NAMES . CREATED_BY ] ,
61- render : ( { row} ) => {
62- if ( ! row . created_by ) {
63- return EMPTY_DATA_PLACEHOLDER ;
64- }
65- return row . created_by ;
73+ ] ;
74+
75+ // Add buildindex-specific columns
76+ if ( isBuildIndex ) {
77+ columns . push (
78+ {
79+ name : COLUMNS_NAMES . STATE ,
80+ header : COLUMNS_TITLES [ COLUMNS_NAMES . STATE ] ,
81+ render : ( { row} ) => {
82+ const metadata = row . metadata as IndexBuildMetadata | undefined ;
83+ if ( ! metadata ?. state ) {
84+ return EMPTY_DATA_PLACEHOLDER ;
85+ }
86+ return metadata . state ;
87+ } ,
6688 } ,
67- } ,
68- {
69- name : COLUMNS_NAMES . CREATE_TIME ,
70- header : COLUMNS_TITLES [ COLUMNS_NAMES . CREATE_TIME ] ,
71- render : ( { row} ) => {
72- if ( ! row . create_time ) {
73- return EMPTY_DATA_PLACEHOLDER ;
74- }
75- return formatDateTime ( parseProtobufTimestampToMs ( row . create_time ) ) ;
89+ {
90+ name : COLUMNS_NAMES . PROGRESS ,
91+ header : COLUMNS_TITLES [ COLUMNS_NAMES . PROGRESS ] ,
92+ render : ( { row} ) => {
93+ const metadata = row . metadata as IndexBuildMetadata | undefined ;
94+ if ( metadata ?. progress === undefined ) {
95+ return EMPTY_DATA_PLACEHOLDER ;
96+ }
97+ return `${ Math . round ( metadata . progress ) } %` ;
98+ } ,
7699 } ,
77- } ,
78- {
79- name : COLUMNS_NAMES . END_TIME ,
80- header : COLUMNS_TITLES [ COLUMNS_NAMES . END_TIME ] ,
81- render : ( { row} ) => {
82- if ( ! row . end_time ) {
83- return EMPTY_DATA_PLACEHOLDER ;
84- }
85- return formatDateTime ( parseProtobufTimestampToMs ( row . end_time ) ) ;
100+ ) ;
101+ } else {
102+ // Add standard columns for non-buildindex operations
103+ columns . push (
104+ {
105+ name : COLUMNS_NAMES . CREATED_BY ,
106+ header : COLUMNS_TITLES [ COLUMNS_NAMES . CREATED_BY ] ,
107+ render : ( { row} ) => {
108+ if ( ! row . created_by ) {
109+ return EMPTY_DATA_PLACEHOLDER ;
110+ }
111+ return row . created_by ;
112+ } ,
86113 } ,
87- } ,
88- {
89- name : COLUMNS_NAMES . DURATION ,
90- header : COLUMNS_TITLES [ COLUMNS_NAMES . DURATION ] ,
91- render : ( { row} ) => {
92- let durationValue = 0 ;
93- if ( ! row . create_time ) {
94- return EMPTY_DATA_PLACEHOLDER ;
95- }
96- const createTime = parseProtobufTimestampToMs ( row . create_time ) ;
97- if ( row . end_time ) {
98- const endTime = parseProtobufTimestampToMs ( row . end_time ) ;
99- durationValue = endTime - createTime ;
100- } else {
101- durationValue = Date . now ( ) - createTime ;
102- }
114+ {
115+ name : COLUMNS_NAMES . CREATE_TIME ,
116+ header : COLUMNS_TITLES [ COLUMNS_NAMES . CREATE_TIME ] ,
117+ render : ( { row} ) => {
118+ if ( ! row . create_time ) {
119+ return EMPTY_DATA_PLACEHOLDER ;
120+ }
121+ return formatDateTime ( parseProtobufTimestampToMs ( row . create_time ) ) ;
122+ } ,
123+ } ,
124+ {
125+ name : COLUMNS_NAMES . END_TIME ,
126+ header : COLUMNS_TITLES [ COLUMNS_NAMES . END_TIME ] ,
127+ render : ( { row} ) => {
128+ if ( ! row . end_time ) {
129+ return EMPTY_DATA_PLACEHOLDER ;
130+ }
131+ return formatDateTime ( parseProtobufTimestampToMs ( row . end_time ) ) ;
132+ } ,
133+ } ,
134+ {
135+ name : COLUMNS_NAMES . DURATION ,
136+ header : COLUMNS_TITLES [ COLUMNS_NAMES . DURATION ] ,
137+ render : ( { row} ) => {
138+ let durationValue = 0 ;
139+ if ( ! row . create_time ) {
140+ return EMPTY_DATA_PLACEHOLDER ;
141+ }
142+ const createTime = parseProtobufTimestampToMs ( row . create_time ) ;
143+ if ( row . end_time ) {
144+ const endTime = parseProtobufTimestampToMs ( row . end_time ) ;
145+ durationValue = endTime - createTime ;
146+ } else {
147+ durationValue = Date . now ( ) - createTime ;
148+ }
103149
104- const durationFormatted =
105- durationValue > HOUR_IN_SECONDS * SECOND_IN_MS
106- ? duration ( durationValue ) . format ( 'hh:mm:ss' )
107- : duration ( durationValue ) . format ( 'mm:ss' ) ;
150+ const durationFormatted =
151+ durationValue > HOUR_IN_SECONDS * SECOND_IN_MS
152+ ? duration ( durationValue ) . format ( 'hh:mm:ss' )
153+ : duration ( durationValue ) . format ( 'mm:ss' ) ;
108154
109- return row . end_time
110- ? durationFormatted
111- : i18n ( 'label_duration-ongoing' , { value : durationFormatted } ) ;
112- } ,
113- } ,
114- {
115- name : 'Actions' ,
116- sortable : false ,
117- resizeable : false ,
118- header : '' ,
119- render : ( { row} ) => {
120- return (
121- < OperationsActions
122- operation = { row }
123- database = { database }
124- refreshTable = { refreshTable }
125- />
126- ) ;
155+ return row . end_time
156+ ? durationFormatted
157+ : i18n ( 'label_duration-ongoing' , { value : durationFormatted } ) ;
158+ } ,
127159 } ,
160+ ) ;
161+ }
162+
163+ // Add Actions column
164+ columns . push ( {
165+ name : 'Actions' ,
166+ sortable : false ,
167+ resizeable : false ,
168+ header : '' ,
169+ render : ( { row} ) => {
170+ return (
171+ < OperationsActions
172+ operation = { row }
173+ database = { database }
174+ refreshTable = { refreshTable }
175+ />
176+ ) ;
128177 } ,
129- ] ;
178+ } ) ;
179+
180+ return columns ;
130181}
131182
132183interface OperationsActionsProps {
0 commit comments