Skip to content

Commit 12d5a08

Browse files
committed
fix: new columns for build index
1 parent 83e36df commit 12d5a08

File tree

5 files changed

+128
-71
lines changed

5 files changed

+128
-71
lines changed

src/containers/Operations/Operations.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export function Operations({database, scrollContainerRef}: OperationsProps) {
6262
<TableWithControlsLayout.Table loading={isLoading} className={b('table')}>
6363
{operations.length > 0 || isLoading ? (
6464
<ResizeableDataTable
65-
columns={getColumns({database, refreshTable})}
65+
columns={getColumns({database, refreshTable, kind})}
6666
columnsWidthLSKey={OPERATIONS_SELECTED_COLUMNS_KEY}
6767
data={operations}
6868
settings={settings}

src/containers/Operations/columns.tsx

Lines changed: 119 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {ActionTooltip, Flex, Icon, Text} from '@gravity-ui/uikit';
66
import {ButtonWithConfirmDialog} from '../../components/ButtonWithConfirmDialog/ButtonWithConfirmDialog';
77
import {CellWithPopover} from '../../components/CellWithPopover/CellWithPopover';
88
import {operationsApi} from '../../store/reducers/operations';
9-
import type {TOperation} from '../../types/api/operations';
9+
import type {IndexBuildMetadata, OperationKind, TOperation} from '../../types/api/operations';
1010
import {EStatusCode} from '../../types/api/operations';
1111
import {EMPTY_DATA_PLACEHOLDER, HOUR_IN_SECONDS, SECOND_IN_MS} from '../../utils/constants';
1212
import createToast from '../../utils/createToast';
@@ -21,11 +21,23 @@ import './Operations.scss';
2121
export 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

132183
interface OperationsActionsProps {

src/containers/Operations/constants.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ export const COLUMNS_NAMES = {
1111
CREATE_TIME: 'create_time',
1212
END_TIME: 'end_time',
1313
DURATION: 'duration',
14+
STATE: 'state',
15+
PROGRESS: 'progress',
1416
} as const;
1517

1618
export const COLUMNS_TITLES = {
@@ -20,6 +22,8 @@ export const COLUMNS_TITLES = {
2022
[COLUMNS_NAMES.CREATE_TIME]: i18n('column_createTime'),
2123
[COLUMNS_NAMES.END_TIME]: i18n('column_endTime'),
2224
[COLUMNS_NAMES.DURATION]: i18n('column_duration'),
25+
[COLUMNS_NAMES.STATE]: i18n('column_state'),
26+
[COLUMNS_NAMES.PROGRESS]: i18n('column_progress'),
2327
} as const;
2428

2529
export const BASE_COLUMNS = [

src/containers/Operations/i18n/en.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
"column_createTime": "Create Time",
1616
"column_endTime": "End Time",
1717
"column_duration": "Duration",
18+
"column_state": "State",
19+
"column_progress": "Progress",
1820
"label_duration-ongoing": "{{value}} (ongoing)",
1921

2022
"header_cancel": "Cancel operation",

src/containers/Operations/useInfiniteOperations.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ export function useInfiniteOperations({
6363
);
6464

6565
// Load initial page when kind/search changes
66-
React.useEffect(() => {
66+
React.useLayoutEffect(() => {
6767
setOperationsList([]);
6868
setNextPageToken(undefined);
6969
loadPageAndUpdate({database, kind, page_size: pageSize}, true);
@@ -108,7 +108,7 @@ export function useInfiniteOperations({
108108
React.useEffect(() => {
109109
const scrollContainer = scrollContainerRef?.current;
110110
if (!scrollContainer) {
111-
return;
111+
return undefined;
112112
}
113113

114114
const handleScroll = () => {

0 commit comments

Comments
 (0)