11import React from 'react' ;
22
33import { NoSearchResults } from '@gravity-ui/illustrations' ;
4+ import { skipToken } from '@reduxjs/toolkit/query' ;
5+ import { isNil } from 'lodash' ;
46
57import type { RenderControls } from '../../../../components/PaginatedTable' ;
68import { ResizeablePaginatedTable } from '../../../../components/PaginatedTable' ;
79import { partitionsApi } from '../../../../store/reducers/partitions/partitions' ;
8- import type { TopicMessageMetadataItem } from '../../../../types/api/topic' ;
10+ import { topicApi } from '../../../../store/reducers/topic' ;
11+ import type { TopicDataRequest , TopicMessageMetadataItem } from '../../../../types/api/topic' ;
912import { useAutoRefreshInterval } from '../../../../utils/hooks' ;
1013import { useSelectedColumns } from '../../../../utils/hooks/useSelectedColumns' ;
1114import { renderPaginatedTableErrorMessage } from '../../../../utils/renderPaginatedTableErrorMessage' ;
@@ -38,8 +41,8 @@ interface TopicDataProps {
3841
3942export function TopicData ( { parentRef, path, database} : TopicDataProps ) {
4043 const [ autoRefreshInterval ] = useAutoRefreshInterval ( ) ;
41- const [ startOffset , setStartOffset ] = React . useState < number | undefined > ( undefined ) ;
42- const [ endOffset , setEndOffset ] = React . useState < number | undefined > ( undefined ) ;
44+ const [ startOffset , setStartOffset ] = React . useState ( 0 ) ;
45+ const [ endOffset , setEndOffset ] = React . useState ( 0 ) ;
4346 const [ fullValue , setFullValue ] = React . useState <
4447 string | TopicMessageMetadataItem [ ] | undefined
4548 > ( undefined ) ;
@@ -52,8 +55,24 @@ export function TopicData({parentRef, path, database}: TopicDataProps) {
5255 topicDataFilter,
5356 handleSelectedOffsetChange,
5457 handleStartTimestampChange,
58+ handleSelectedPartitionChange,
5559 } = useTopicDataQueryParams ( ) ;
5660
61+ const queryParams = React . useMemo ( ( ) => {
62+ if ( isNil ( selectedPartition ) ) {
63+ return skipToken ;
64+ }
65+ const params : TopicDataRequest = { database, path, partition : selectedPartition , limit : 1 } ;
66+ if ( startTimestamp ) {
67+ params . read_timestamp = startTimestamp ;
68+ } else {
69+ params . offset = selectedOffset ?? 0 ;
70+ }
71+ return params ;
72+ } , [ selectedPartition , selectedOffset , startTimestamp , database , path ] ) ;
73+
74+ const { currentData, isFetching} = topicApi . useGetTopicDataQuery ( queryParams ) ;
75+
5776 const {
5877 data : partitions ,
5978 isLoading : partitionsLoading ,
@@ -74,16 +93,19 @@ export function TopicData({parentRef, path, database}: TopicDataProps) {
7493 }
7594 } , [ selectedPartition , partitions ] ) ;
7695
77- const tableFilters = React . useMemo ( ( ) => {
78- return {
79- path,
80- database,
81- partition : selectedPartition ?? '' ,
82- selectedOffset : safeParseNumber ( selectedOffset ) ,
83- startTimestamp : safeParseNumber ( startTimestamp ) ,
84- topicDataFilter,
85- } ;
86- } , [ path , database , selectedPartition , selectedOffset , startTimestamp , topicDataFilter ] ) ;
96+ React . useEffect ( ( ) => {
97+ if ( partitions && partitions . length && isNil ( selectedPartition ) ) {
98+ handleSelectedPartitionChange ( partitions [ 0 ] . partitionId ) ;
99+ handleSelectedOffsetChange ( undefined ) ;
100+ handleStartTimestampChange ( undefined ) ;
101+ }
102+ } , [
103+ partitions ,
104+ selectedPartition ,
105+ handleSelectedPartitionChange ,
106+ handleSelectedOffsetChange ,
107+ handleStartTimestampChange ,
108+ ] ) ;
87109
88110 const { columnsToShow, columnsToSelect, setColumns} = useSelectedColumns (
89111 getAllColumns ( setFullValue ) ,
@@ -93,6 +115,59 @@ export function TopicData({parentRef, path, database}: TopicDataProps) {
93115 REQUIRED_TOPIC_DATA_COLUMNS ,
94116 ) ;
95117
118+ const emptyData = React . useMemo ( ( ) => ! currentData ?. Messages ?. length , [ currentData ] ) ;
119+
120+ const tableFilters = React . useMemo ( ( ) => {
121+ return {
122+ path,
123+ database,
124+ partition : selectedPartition ?? '' ,
125+ isEmpty : emptyData ,
126+ } ;
127+ } , [ path , database , selectedPartition , emptyData ] ) ;
128+
129+ const scrollToOffset = React . useCallback (
130+ ( newOffset : number ) => {
131+ const scrollTop = ( newOffset - ( startOffset ?? 0 ) ) * 41 ;
132+ const normalizedScrollTop = Math . max ( 0 , scrollTop ) ;
133+ parentRef . current ?. scrollTo ( {
134+ top : normalizedScrollTop ,
135+ behavior : 'instant' ,
136+ } ) ;
137+ } ,
138+ [ startOffset , parentRef ] ,
139+ ) ;
140+
141+ React . useEffect ( ( ) => {
142+ if ( isFetching ) {
143+ return ;
144+ }
145+ const messages = currentData ?. Messages ;
146+ if ( messages ?. length ) {
147+ const messageOffset = safeParseNumber ( messages [ 0 ] . Offset ) ;
148+ //scroll when table is already rendered and calculated it's state
149+ setTimeout ( ( ) => {
150+ scrollToOffset ( messageOffset ) ;
151+ } , 0 ) ;
152+ }
153+ } , [ currentData , isFetching , scrollToOffset ] ) ;
154+
155+ const scrollToStartOffset = React . useCallback ( ( ) => {
156+ parentRef . current ?. scrollTo ( {
157+ top : 0 ,
158+ behavior : 'smooth' ,
159+ } ) ;
160+ } , [ parentRef ] ) ;
161+
162+ const scrollToEndOffset = React . useCallback ( ( ) => {
163+ if ( parentRef . current ) {
164+ parentRef . current . scrollTo ( {
165+ top : parentRef . current . scrollHeight - parentRef . current . clientHeight ,
166+ behavior : 'smooth' ,
167+ } ) ;
168+ }
169+ } , [ parentRef ] ) ;
170+
96171 const renderControls : RenderControls = ( ) => {
97172 return (
98173 < TopicDataControls
@@ -105,6 +180,8 @@ export function TopicData({parentRef, path, database}: TopicDataProps) {
105180 partitionsError = { partitionsError }
106181 initialOffset = { startOffset }
107182 endOffset = { endOffset }
183+ scrollToStartOffset = { scrollToStartOffset }
184+ scrollToEndOffset = { scrollToEndOffset }
108185 />
109186 ) ;
110187 } ;
@@ -132,19 +209,22 @@ export function TopicData({parentRef, path, database}: TopicDataProps) {
132209 ) ;
133210 } ;
134211
212+ const getTopicData = React . useMemo (
213+ ( ) => generateTopicDataGetter ( { setEndOffset, setStartOffset} ) ,
214+ [ ] ,
215+ ) ;
216+
135217 return (
136218 < React . Fragment >
137219 < FullValue value = { fullValue } onClose = { ( ) => setFullValue ( undefined ) } />
138220 < ResizeablePaginatedTable
139221 columnsWidthLSKey = { TOPIC_DATA_COLUMNS_WIDTH_LS_KEY }
140222 parentRef = { parentRef }
141223 columns = { columnsToShow }
142- fetchData = { generateTopicDataGetter ( {
143- setStartOffset,
144- setEndOffset,
145- initialOffset : startOffset ,
146- } ) }
224+ fetchData = { getTopicData }
225+ initialEntitiesCount = { endOffset - startOffset }
147226 limit = { 50 }
227+ startOffset = { startOffset }
148228 renderControls = { renderControls }
149229 renderErrorMessage = { renderPaginatedTableErrorMessage }
150230 renderEmptyDataMessage = { renderEmptyDataMessage }
0 commit comments