@@ -3,7 +3,7 @@ import React from 'react';
3
3
import { Flex , Tabs } from '@gravity-ui/uikit' ;
4
4
import { skipToken } from '@reduxjs/toolkit/query' ;
5
5
import { Helmet } from 'react-helmet-async' ;
6
- import { useLocation , useParams } from 'react-router-dom' ;
6
+ import { useParams } from 'react-router-dom' ;
7
7
import { StringParam , useQueryParams } from 'use-query-params' ;
8
8
import { z } from 'zod' ;
9
9
@@ -13,12 +13,14 @@ import {ResponseError} from '../../components/Errors/ResponseError';
13
13
import { InternalLink } from '../../components/InternalLink' ;
14
14
import { LoaderWrapper } from '../../components/LoaderWrapper/LoaderWrapper' ;
15
15
import { PageMetaWithAutorefresh } from '../../components/PageMeta/PageMeta' ;
16
- import { getTabletPagePath , parseQuery } from '../../routes' ;
16
+ import { getTabletPagePath } from '../../routes' ;
17
17
import { selectIsUserAllowedToMakeChanges } from '../../store/reducers/authentication/authentication' ;
18
18
import { setHeaderBreadcrumbs } from '../../store/reducers/header/header' ;
19
19
import { tabletApi } from '../../store/reducers/tablet' ;
20
20
import { EFlag } from '../../types/api/enums' ;
21
- import type { EType } from '../../types/api/tablet' ;
21
+ import type { TTabletStateInfo } from '../../types/api/tablet' ;
22
+ import { EType } from '../../types/api/tablet' ;
23
+ import type { ITabletPreparedHistoryItem } from '../../types/store/tablet' ;
22
24
import { cn } from '../../utils/cn' ;
23
25
import { CLUSTER_DEFAULT_TITLE } from '../../utils/constants' ;
24
26
import { useAutoRefreshInterval , useTypedDispatch , useTypedSelector } from '../../utils/hooks' ;
@@ -56,185 +58,174 @@ const TABLET_PAGE_TABS = [
56
58
] ;
57
59
58
60
const tabletTabSchema = z . nativeEnum ( TABLET_TABS_IDS ) . catch ( TABLET_TABS_IDS . history ) ;
61
+ const eTypeSchema = z . nativeEnum ( EType ) . or ( z . undefined ( ) ) . catch ( undefined ) ;
59
62
60
- export const Tablet = ( ) => {
63
+ export function Tablet ( ) {
61
64
const dispatch = useTypedDispatch ( ) ;
62
- const location = useLocation ( ) ;
63
- const isUserAllowedToMakeChanges = useTypedSelector ( selectIsUserAllowedToMakeChanges ) ;
64
65
65
66
const { id} = useParams < { id : string } > ( ) ;
66
67
67
- const [ { activeTab} , setParams ] = useQueryParams ( {
68
- activeTab : StringParam ,
68
+ const [
69
+ {
70
+ nodeId : queryNodeId ,
71
+ tenantName : queryTenantName ,
72
+ type : queryTabletType ,
73
+ clusterName : queryClusterName ,
74
+ } ,
75
+ ] = useQueryParams ( {
76
+ nodeId : StringParam ,
77
+ tenantName : StringParam ,
78
+ type : StringParam ,
79
+ clusterName : StringParam ,
69
80
} ) ;
70
81
71
- const tabletTab = tabletTabSchema . parse ( activeTab ) ;
72
-
73
- const {
74
- nodeId : queryNodeId ,
75
- tenantName : queryTenantName ,
76
- type : queryTabletType ,
77
- clusterName : queryClusterName ,
78
- } = parseQuery ( location ) ;
79
-
80
82
const [ autoRefreshInterval ] = useAutoRefreshInterval ( ) ;
81
- const { currentData, isFetching, error, refetch } = tabletApi . useGetTabletQuery (
83
+ const { currentData, isFetching, error} = tabletApi . useGetTabletQuery (
82
84
{ id, database : queryTenantName ?. toString ( ) } ,
83
85
{ pollingInterval : autoRefreshInterval } ,
84
86
) ;
85
87
86
88
const loading = isFetching && currentData === undefined ;
87
- const { id : tabletId , data : tablet = { } , history = [ ] } = currentData || { } ;
89
+ const { data : tablet = { } , history = [ ] } = currentData || { } ;
88
90
89
91
const { currentData : tenantPath } = tabletApi . useGetTabletDescribeQuery (
90
92
tablet . TenantId ? { tenantId : tablet . TenantId } : skipToken ,
91
93
) ;
92
94
93
- const hasHiveId = hasHive ( tablet . HiveId ) ;
95
+ const nodeId = tablet . NodeId ?? queryNodeId ;
96
+ const tenantName = ( tenantPath || queryTenantName ) ?? undefined ;
94
97
95
- const noAdvancedInfo = ! isUserAllowedToMakeChanges || ! hasHiveId ;
96
-
97
- React . useEffect ( ( ) => {
98
- if ( loading ) {
99
- return ;
100
- }
101
- if ( noAdvancedInfo && TABLET_PAGE_TABS . find ( ( { id} ) => id === tabletTab ) ?. isAdvanced ) {
102
- setParams ( { activeTab : TABLET_TABS_IDS . history } ) ;
103
- }
104
- } , [ noAdvancedInfo , tabletTab , setParams , loading ] ) ;
105
-
106
- const {
107
- currentData : advancedData ,
108
- refetch : refetchAdvancedInfo ,
109
- isFetching : isFetchingAdvancedData ,
110
- } = tabletApi . useGetAdvancedTableInfoQuery (
111
- { id, hiveId : tablet . HiveId } ,
112
- {
113
- pollingInterval : autoRefreshInterval ,
114
- skip : noAdvancedInfo || activeTab !== 'channels' ,
115
- } ,
116
- ) ;
117
-
118
- const refetchTabletInfo = React . useCallback ( async ( ) => {
119
- await Promise . all ( [ refetch ( ) , refetchAdvancedInfo ( ) ] ) ;
120
- } , [ refetch , refetchAdvancedInfo ] ) ;
121
-
122
- const nodeId = tablet . NodeId ?. toString ( ) || queryNodeId ?. toString ( ) ;
123
- const tenantName = tenantPath || queryTenantName ?. toString ( ) ;
124
-
125
- const type = tablet . Type || ( queryTabletType ?. toString ( ) as EType | undefined ) ;
98
+ const tabletType = tablet . Type || eTypeSchema . parse ( queryTabletType ) ;
126
99
127
100
React . useEffect ( ( ) => {
128
101
dispatch (
129
102
setHeaderBreadcrumbs ( 'tablet' , {
130
103
nodeIds : nodeId ? [ nodeId ] : [ ] ,
131
104
tenantName,
132
105
tabletId : id ,
133
- tabletType : type ,
106
+ tabletType,
134
107
} ) ,
135
108
) ;
136
- } , [ dispatch , tenantName , id , nodeId , type ] ) ;
109
+ } , [ dispatch , tenantName , id , nodeId , tabletType ] ) ;
137
110
138
- const renderPageMeta = ( ) => {
139
- const { Leader, Type} = tablet ;
140
- const database = tenantName ? `${ i18n ( 'tablet.meta-database' ) } : ${ tenantName } ` : undefined ;
141
- const type = Type ? Type : undefined ;
142
- const follower = Leader === false ? i18n ( 'tablet.meta-follower' ) . toUpperCase ( ) : undefined ;
111
+ const { Leader, Type} = tablet ;
112
+ const database = tenantName ? `${ i18n ( 'tablet.meta-database' ) } : ${ tenantName } ` : undefined ;
113
+ const type = Type ? Type : undefined ;
114
+ const follower = Leader === false ? i18n ( 'tablet.meta-follower' ) . toUpperCase ( ) : undefined ;
143
115
144
- return < PageMetaWithAutorefresh items = { [ database , type , follower ] } /> ;
145
- } ;
146
-
147
- const renderHelmet = ( ) => {
148
- return (
116
+ return (
117
+ < Flex gap = { 5 } direction = "column" className = { b ( ) } >
149
118
< Helmet >
150
119
< title > { `${ id } — ${ i18n ( 'tablet.header' ) } — ${
151
120
tenantName || queryClusterName || CLUSTER_DEFAULT_TITLE
152
121
} `} </ title >
153
122
</ Helmet >
154
- ) ;
155
- } ;
156
-
157
- const renderTabs = ( ) => {
158
- return (
159
- //block wrapper for tabs
160
- < div >
161
- < Tabs
162
- size = "l"
163
- items = { TABLET_PAGE_TABS . filter ( ( { isAdvanced} ) =>
164
- isAdvanced ? ! noAdvancedInfo : true ,
165
- ) }
166
- activeTab = { tabletTab }
167
- wrapTo = { ( { id} , tabNode ) => {
168
- const path = tabletId
169
- ? getTabletPagePath ( tabletId , { activeTab : id } )
170
- : undefined ;
171
- return (
172
- < InternalLink to = { path } key = { id } >
173
- { tabNode }
174
- </ InternalLink >
175
- ) ;
176
- } }
123
+ < PageMetaWithAutorefresh items = { [ database , type , follower ] } />
124
+ < LoaderWrapper loading = { loading } size = "l" >
125
+ { error ? < ResponseError error = { error } /> : null }
126
+ { currentData ? < TabletContent id = { id } tablet = { tablet } history = { history } /> : null }
127
+ </ LoaderWrapper >
128
+ </ Flex >
129
+ ) ;
130
+ }
131
+
132
+ function TabletContent ( {
133
+ id,
134
+ tablet,
135
+ history,
136
+ } : {
137
+ id : string ;
138
+ tablet : TTabletStateInfo ;
139
+ history : ITabletPreparedHistoryItem [ ] ;
140
+ } ) {
141
+ const isEmpty = ! Object . keys ( tablet ) . length ;
142
+ const { Overall, HiveId} = tablet ;
143
+
144
+ return (
145
+ < EmptyStateWrapper
146
+ title = { i18n ( 'emptyState' ) }
147
+ className = { b ( 'placeholder' ) }
148
+ isEmpty = { isEmpty }
149
+ >
150
+ < Flex gap = { 5 } direction = "column" >
151
+ < EntityPageTitle
152
+ entityName = { i18n ( 'tablet.header' ) }
153
+ status = { Overall ?? EFlag . Grey }
154
+ id = { id }
177
155
/>
178
- </ div >
179
- ) ;
180
- } ;
181
-
182
- const renderTabsContent = ( ) => {
183
- switch ( tabletTab ) {
184
- case 'channels' : {
185
- return (
186
- < LoaderWrapper
187
- loading = { isFetchingAdvancedData && advancedData === undefined }
188
- size = "l"
189
- >
190
- < TabletStorageInfo data = { advancedData } />
191
- </ LoaderWrapper >
192
- ) ;
193
- }
194
- case 'history' : {
195
- return < TabletTable history = { history } /> ;
196
- }
197
- default :
198
- return null ;
199
- }
200
- } ;
156
+ < TabletControls tablet = { tablet } />
157
+ < TabletInfo tablet = { tablet } />
158
+ </ Flex >
159
+ < TabletTabs id = { id } hiveId = { HiveId } history = { history } />
160
+ </ EmptyStateWrapper >
161
+ ) ;
162
+ }
163
+
164
+ function TabletTabs ( {
165
+ id,
166
+ hiveId,
167
+ history,
168
+ } : {
169
+ id : string ;
170
+ hiveId ?: string ;
171
+ history : ITabletPreparedHistoryItem [ ] ;
172
+ } ) {
173
+ const [ { activeTab} , setParams ] = useQueryParams ( { activeTab : StringParam } ) ;
174
+ const isUserAllowedToMakeChanges = useTypedSelector ( selectIsUserAllowedToMakeChanges ) ;
175
+
176
+ const noAdvancedInfo = ! isUserAllowedToMakeChanges || ! hasHive ( hiveId ) ;
201
177
202
- const renderView = ( ) => {
203
- if ( error && ! currentData ) {
204
- return < ResponseError error = { error } /> ;
178
+ let tabletTab = tabletTabSchema . parse ( activeTab ) ;
179
+ if ( noAdvancedInfo && TABLET_PAGE_TABS . find ( ( tab ) => tab . id === tabletTab ) ?. isAdvanced ) {
180
+ tabletTab = TABLET_TABS_IDS . history ;
181
+ }
182
+
183
+ React . useEffect ( ( ) => {
184
+ if ( activeTab !== tabletTab ) {
185
+ setParams ( { activeTab : tabletTab } , 'replaceIn' ) ;
205
186
}
187
+ } , [ activeTab , tabletTab , setParams ] ) ;
206
188
207
- const { TabletId, Overall} = tablet ;
208
- return (
209
- < React . Fragment >
210
- { error ? < ResponseError error = { error } /> : null }
211
- < Flex gap = { 5 } direction = "column" >
212
- < EntityPageTitle
213
- entityName = { i18n ( 'tablet.header' ) }
214
- status = { Overall ?? EFlag . Grey }
215
- id = { TabletId }
216
- />
217
- < TabletControls tablet = { tablet } fetchData = { refetchTabletInfo } />
218
- < TabletInfo tablet = { tablet } />
219
- </ Flex >
220
- </ React . Fragment >
221
- ) ;
222
- } ;
223
189
return (
224
- < Flex gap = { 5 } direction = "column" className = { b ( ) } >
225
- { renderHelmet ( ) }
226
- { renderPageMeta ( ) }
227
- < LoaderWrapper loading = { loading } size = "l" >
228
- < EmptyStateWrapper
229
- title = { i18n ( 'emptyState' ) }
230
- className = { b ( 'placeholder' ) }
231
- isEmpty = { ! tablet || ! Object . keys ( tablet ) . length }
232
- >
233
- { renderView ( ) }
234
- { renderTabs ( ) }
235
- { renderTabsContent ( ) }
236
- </ EmptyStateWrapper >
237
- </ LoaderWrapper >
190
+ < Flex gap = { 5 } direction = "column" >
191
+ < Tabs
192
+ size = "l"
193
+ items = { TABLET_PAGE_TABS . filter ( ( { isAdvanced} ) =>
194
+ isAdvanced ? ! noAdvancedInfo : true ,
195
+ ) }
196
+ activeTab = { tabletTab }
197
+ wrapTo = { ( tab , tabNode ) => {
198
+ const path = getTabletPagePath ( id , { activeTab : tab . id } ) ;
199
+ return (
200
+ < InternalLink to = { path } key = { tab . id } >
201
+ { tabNode }
202
+ </ InternalLink >
203
+ ) ;
204
+ } }
205
+ />
206
+ { tabletTab === 'history' ? < TabletTable history = { history } /> : null }
207
+ { tabletTab === 'channels' && ! noAdvancedInfo ? (
208
+ < Channels id = { id } hiveId = { hiveId } />
209
+ ) : null }
238
210
</ Flex >
239
211
) ;
240
- } ;
212
+ }
213
+
214
+ function Channels ( { id, hiveId} : { id : string ; hiveId : string } ) {
215
+ const [ autoRefreshInterval ] = useAutoRefreshInterval ( ) ;
216
+ const { currentData, error, isFetching} = tabletApi . useGetAdvancedTableInfoQuery (
217
+ { id, hiveId} ,
218
+ {
219
+ pollingInterval : autoRefreshInterval ,
220
+ } ,
221
+ ) ;
222
+
223
+ const loading = isFetching && currentData === undefined ;
224
+
225
+ return (
226
+ < LoaderWrapper loading = { loading } size = "l" >
227
+ { error ? < ResponseError error = { error } /> : null }
228
+ { currentData ? < TabletStorageInfo data = { currentData } /> : null }
229
+ </ LoaderWrapper >
230
+ ) ;
231
+ }
0 commit comments