11import React from 'react' ;
22
33import { ChevronsCollapseVertical , ChevronsExpandVertical } from '@gravity-ui/icons' ;
4- import { Button , Flex , Icon , SegmentedRadioGroup , Select , Text } from '@gravity-ui/uikit' ;
4+ import { Button , Flex , Icon , Select , Text } from '@gravity-ui/uikit' ;
55import { StringParam , useQueryParams } from 'use-query-params' ;
66import { z } from 'zod' ;
77
@@ -15,10 +15,9 @@ import {useAutoRefreshInterval} from '../../utils/hooks';
1515import type { PreparedVersion , VersionsDataMap } from '../../utils/versions/types' ;
1616
1717import { GroupedNodesTree } from './GroupedNodesTree/GroupedNodesTree' ;
18- import type { NodeType } from './constants' ;
19- import { NODE_TYPES , NODE_TYPES_TITLE } from './constants' ;
2018import { getGroupedStorageNodes , getGroupedTenantNodes , getOtherNodes } from './groupNodes' ;
2119import i18n from './i18n' ;
20+ import type { GroupedNodesItem } from './types' ;
2221import { GroupByValue } from './types' ;
2322import { useGetPreparedVersions , useVersionsDataMap } from './utils' ;
2423
@@ -62,20 +61,15 @@ interface VersionsProps {
6261 versionsDataMap ?: VersionsDataMap ;
6362}
6463
65- const nodeTypeSchema = z . nativeEnum ( NODE_TYPES ) . catch ( NODE_TYPES . storage ) ;
6664const groupByValueSchema = z . nativeEnum ( GroupByValue ) . catch ( GroupByValue . VERSION ) ;
6765
6866function Versions ( { preparedVersions, nodes, versionsDataMap} : VersionsProps ) {
69- const [ { nodeType : rawNodeType , groupBy : rawGroupByValue } , setQueryParams ] = useQueryParams ( {
70- nodeType : StringParam ,
67+ const [ { groupBy : rawGroupByValue } , setQueryParams ] = useQueryParams ( {
7168 groupBy : StringParam ,
7269 } ) ;
7370
74- const nodeType = nodeTypeSchema . parse ( rawNodeType ) ;
7571 const groupByValue = groupByValueSchema . parse ( rawGroupByValue ) ;
7672
77- const [ expanded , setExpanded ] = React . useState ( false ) ;
78-
7973 const tenantNodes = React . useMemo ( ( ) => {
8074 return getGroupedTenantNodes ( nodes , versionsDataMap , groupByValue ) ;
8175 } , [ groupByValue , nodes , versionsDataMap ] ) ;
@@ -89,167 +83,100 @@ function Versions({preparedVersions, nodes, versionsDataMap}: VersionsProps) {
8983 const handleGroupByValueChange = ( value : string ) => {
9084 setQueryParams ( { groupBy : value as GroupByValue } , 'replaceIn' ) ;
9185 } ;
92- const handleNodeTypeChange = ( value : string ) => {
93- setQueryParams ( { nodeType : value as NodeType } , 'replaceIn' ) ;
94- } ;
9586
96- const renderExpandButton = ( ) => {
87+ const renderGroupControl = ( ) => {
88+ const options = [
89+ { value : GroupByValue . TENANT , content : i18n ( 'title_database' ) } ,
90+ { value : GroupByValue . VERSION , content : i18n ( 'title_version' ) } ,
91+ ] ;
9792 return (
98- < Button onClick = { ( ) => setExpanded ( ( value ) => ! value ) } >
99- < Icon data = { expanded ? ChevronsCollapseVertical : ChevronsExpandVertical } />
100- { expanded ? i18n ( 'action_collapse' ) : i18n ( 'action_expand' ) }
101- </ Button >
93+ < Select
94+ label = { i18n ( 'group-by' ) }
95+ value = { [ groupByValue ] }
96+ options = { options }
97+ onUpdate = { ( values ) => handleGroupByValueChange ( values [ 0 ] ) }
98+ width = { 200 }
99+ size = "m"
100+ />
102101 ) ;
103102 } ;
104103
105- const renderNodeTypeRadio = ( ) => {
106- const options = [
107- < SegmentedRadioGroup . Option value = { NODE_TYPES . storage } >
108- { NODE_TYPES_TITLE . storage }
109- </ SegmentedRadioGroup . Option > ,
110- < SegmentedRadioGroup . Option value = { NODE_TYPES . database } >
111- { NODE_TYPES_TITLE . database }
112- </ SegmentedRadioGroup . Option > ,
113- ] ;
104+ return (
105+ < Flex className = { b ( ) } direction = { 'column' } gap = { 6 } >
106+ < Flex gap = { 3 } direction = { 'column' } className = { b ( 'overall' ) } >
107+ < Text variant = "subheader-3" > { i18n ( 'title_overall' ) } </ Text >
108+ < VersionsBar preparedVersions = { preparedVersions } size = "m" />
109+ </ Flex >
114110
115- if ( otherNodes ?. length ) {
116- options . push (
117- < SegmentedRadioGroup . Option value = { NODE_TYPES . other } >
118- { NODE_TYPES_TITLE . other }
119- </ SegmentedRadioGroup . Option > ,
120- ) ;
121- }
111+ < VersionsSection sectionTitle = { i18n ( 'title_storage-nodes' ) } nodes = { storageNodes } />
112+ < VersionsSection
113+ sectionTitle = { i18n ( 'title_database-nodes' ) }
114+ nodes = { tenantNodes }
115+ renderControls = { renderGroupControl }
116+ />
117+ < VersionsSection sectionTitle = { i18n ( 'title_other-nodes' ) } nodes = { otherNodes } />
118+ </ Flex >
119+ ) ;
120+ }
122121
123- return (
124- < SegmentedRadioGroup value = { nodeType } onUpdate = { handleNodeTypeChange } >
125- { options }
126- </ SegmentedRadioGroup >
127- ) ;
128- } ;
122+ function VersionsSection ( {
123+ sectionTitle,
124+ renderControls,
125+ nodes,
126+ } : {
127+ sectionTitle : string ;
128+ renderControls ?: ( ) => React . ReactNode ;
129+ nodes ?: GroupedNodesItem [ ] ;
130+ } ) {
131+ const [ expanded , setExpanded ] = React . useState ( false ) ;
129132
130- const renderGroupControl = ( ) => {
131- if ( nodeType === NODE_TYPES . database ) {
132- const options = [
133- { value : GroupByValue . TENANT , content : i18n ( 'title_database' ) } ,
134- { value : GroupByValue . VERSION , content : i18n ( 'title_version' ) } ,
135- ] ;
136- return (
137- < Select
138- label = { i18n ( 'group-by' ) }
139- value = { [ groupByValue ] }
140- options = { options }
141- onUpdate = { ( values ) => handleGroupByValueChange ( values [ 0 ] ) }
142- width = { 200 }
143- size = "m"
144- />
145- ) ;
146- }
133+ if ( ! nodes ?. length ) {
147134 return null ;
148- } ;
149- const renderControls = ( ) => {
135+ }
136+
137+ const renderExpandButton = ( ) => {
150138 return (
151- < Flex gap = { 3 } className = { b ( 'controls' ) } >
152- { renderNodeTypeRadio ( ) }
153- { renderGroupControl ( ) }
154- { renderExpandButton ( ) }
155- </ Flex >
139+ < Button onClick = { ( ) => setExpanded ( ( value ) => ! value ) } >
140+ < Icon data = { expanded ? ChevronsCollapseVertical : ChevronsExpandVertical } />
141+ { expanded ? i18n ( 'action_collapse' ) : i18n ( 'action_expand' ) }
142+ </ Button >
156143 ) ;
157144 } ;
158145
159- const renderStorageNodes = ( ) => {
160- if ( storageNodes ?. length ) {
161- return storageNodes . map ( ( { title, nodes : itemNodes , items, versionColor} ) => (
146+ const renderNodes = ( ) => {
147+ return nodes . map (
148+ ( {
149+ title,
150+ isDatabase,
151+ nodes : itemNodes ,
152+ items,
153+ versionColor,
154+ preparedVersions : nodesVersions ,
155+ } ) => (
162156 < GroupedNodesTree
163- key = { `storage-nodes- ${ title } ` }
157+ key = { title }
164158 title = { title }
159+ isDatabase = { isDatabase }
165160 nodes = { itemNodes }
166161 items = { items }
167- expanded = { expanded }
168162 versionColor = { versionColor }
163+ expanded = { expanded }
164+ preparedVersions = { nodesVersions }
169165 />
170- ) ) ;
171- }
172- return null ;
173- } ;
174- const renderDatabaseNodes = ( ) => {
175- if ( tenantNodes ?. length ) {
176- return tenantNodes . map (
177- ( {
178- title,
179- isDatabase,
180- nodes : itemNodes ,
181- items,
182- versionColor,
183- preparedVersions : nodesVersions ,
184- } ) => (
185- < GroupedNodesTree
186- key = { `tenant-nodes-${ title } ` }
187- title = { title }
188- isDatabase = { isDatabase }
189- nodes = { itemNodes }
190- items = { items }
191- expanded = { expanded }
192- versionColor = { versionColor }
193- preparedVersions = { nodesVersions }
194- />
195- ) ,
196- ) ;
197- }
198- return null ;
199- } ;
200-
201- const renderOtherNodes = ( ) => {
202- if ( otherNodes ?. length ) {
203- return otherNodes . map (
204- ( {
205- title,
206- nodes : itemNodes ,
207- items,
208- versionColor,
209- preparedVersions : nodesVersions ,
210- } ) => (
211- < GroupedNodesTree
212- key = { `other-nodes-${ title } ` }
213- title = { title }
214- nodes = { itemNodes }
215- items = { items }
216- versionColor = { versionColor }
217- expanded = { expanded }
218- preparedVersions = { nodesVersions }
219- />
220- ) ,
221- ) ;
222- }
223- return null ;
224- } ;
225-
226- const renderContent = ( ) => {
227- switch ( nodeType ) {
228- case NODE_TYPES . storage :
229- return renderStorageNodes ( ) ;
230- case NODE_TYPES . database :
231- return renderDatabaseNodes ( ) ;
232- case NODE_TYPES . other :
233- return renderOtherNodes ( ) ;
234- default :
235- return null ;
236- }
166+ ) ,
167+ ) ;
237168 } ;
238169
239- const overallContent = (
240- < Flex gap = { 3 } direction = { 'column' } className = { b ( 'overall' ) } >
241- < Text variant = "subheader-3" > { i18n ( 'title_overall' ) } </ Text >
242- < VersionsBar preparedVersions = { preparedVersions } size = "m" />
243- </ Flex >
244- ) ;
245-
246170 return (
247- < div className = { b ( ) } >
248- { overallContent }
249- { renderControls ( ) }
250- < Flex direction = { 'column' } gap = { 3 } >
251- { renderContent ( ) }
171+ < Flex gap = { 3 } direction = { 'column' } >
172+ < Flex justifyContent = { 'space-between' } >
173+ < Flex gap = { 3 } >
174+ < Text variant = "subheader-3" > { sectionTitle } </ Text >
175+ { renderControls ?.( ) }
176+ </ Flex >
177+ { renderExpandButton ( ) }
252178 </ Flex >
253- </ div >
179+ { renderNodes ( ) }
180+ </ Flex >
254181 ) ;
255182}
0 commit comments