1
1
import React from 'react' ;
2
2
3
+ import { CirclePlus , TrashBin } from '@gravity-ui/icons' ;
3
4
import type { Column } from '@gravity-ui/react-data-table' ;
4
5
import DataTable from '@gravity-ui/react-data-table' ;
5
- import { Button } from '@gravity-ui/uikit' ;
6
+ import type { DropdownMenuItem } from '@gravity-ui/uikit' ;
7
+ import { Button , DropdownMenu , Icon } from '@gravity-ui/uikit' ;
6
8
7
9
import { EntitiesCount } from '../../components/EntitiesCount' ;
8
10
import { ResponseError } from '../../components/Errors/ResponseError' ;
@@ -13,7 +15,10 @@ import {ResizeableDataTable} from '../../components/ResizeableDataTable/Resizeab
13
15
import { Search } from '../../components/Search' ;
14
16
import { TableWithControlsLayout } from '../../components/TableWithControlsLayout/TableWithControlsLayout' ;
15
17
import { TenantNameWrapper } from '../../components/TenantNameWrapper/TenantNameWrapper' ;
16
- import { clusterName } from '../../store' ;
18
+ import {
19
+ useCreateDatabaseFeatureAvailable ,
20
+ useDeleteDatabaseFeatureAvailable ,
21
+ } from '../../store/reducers/capabilities/hooks' ;
17
22
import {
18
23
ProblemFilterValues ,
19
24
changeFilter ,
@@ -28,6 +33,7 @@ import {
28
33
import { setSearchValue , tenantsApi } from '../../store/reducers/tenants/tenants' ;
29
34
import type { PreparedTenant } from '../../store/reducers/tenants/types' ;
30
35
import type { AdditionalTenantsProps } from '../../types/additionalProps' ;
36
+ import { uiFactory } from '../../uiFactory/uiFactory' ;
31
37
import { cn } from '../../utils/cn' ;
32
38
import { DEFAULT_TABLE_SETTINGS } from '../../utils/constants' ;
33
39
import {
@@ -36,6 +42,9 @@ import {
36
42
formatStorageValuesToGb ,
37
43
} from '../../utils/dataFormatters/dataFormatters' ;
38
44
import { useAutoRefreshInterval , useTypedDispatch , useTypedSelector } from '../../utils/hooks' ;
45
+ import { useClusterNameFromQuery } from '../../utils/hooks/useDatabaseFromQuery' ;
46
+
47
+ import i18n from './i18n' ;
39
48
40
49
import './Tenants.scss' ;
41
50
@@ -50,13 +59,20 @@ interface TenantsProps {
50
59
export const Tenants = ( { additionalTenantsProps} : TenantsProps ) => {
51
60
const dispatch = useTypedDispatch ( ) ;
52
61
62
+ const clusterName = useClusterNameFromQuery ( ) ;
63
+
53
64
const [ autoRefreshInterval ] = useAutoRefreshInterval ( ) ;
54
65
const { currentData, isFetching, error} = tenantsApi . useGetTenantsInfoQuery (
55
66
{ clusterName} ,
56
67
{ pollingInterval : autoRefreshInterval } ,
57
68
) ;
58
69
const loading = isFetching && currentData === undefined ;
59
70
71
+ const isCreateDBAvailable =
72
+ useCreateDatabaseFeatureAvailable ( ) && uiFactory . onCreateDB !== undefined ;
73
+ const isDeleteDBAvailable =
74
+ useDeleteDatabaseFeatureAvailable ( ) && uiFactory . onDeleteDB !== undefined ;
75
+
60
76
const tenants = useTypedSelector ( ( state ) => selectTenants ( state , clusterName ) ) ;
61
77
const searchValue = useTypedSelector ( selectTenantsSearchValue ) ;
62
78
const filteredTenants = useTypedSelector ( ( state ) => selectFilteredTenants ( state , clusterName ) ) ;
@@ -70,6 +86,23 @@ export const Tenants = ({additionalTenantsProps}: TenantsProps) => {
70
86
dispatch ( setSearchValue ( value ) ) ;
71
87
} ;
72
88
89
+ const renderCreateDBButton = ( ) => {
90
+ if ( isCreateDBAvailable && clusterName ) {
91
+ return (
92
+ < Button
93
+ view = "action"
94
+ onClick = { ( ) => uiFactory . onCreateDB ?.( { clusterName} ) }
95
+ className = { b ( 'create-database' ) }
96
+ >
97
+ < Icon data = { CirclePlus } />
98
+ { i18n ( 'create-database' ) }
99
+ </ Button >
100
+ ) ;
101
+ }
102
+
103
+ return null ;
104
+ } ;
105
+
73
106
const renderControls = ( ) => {
74
107
return (
75
108
< React . Fragment >
@@ -86,6 +119,7 @@ export const Tenants = ({additionalTenantsProps}: TenantsProps) => {
86
119
label = { 'Databases' }
87
120
loading = { loading }
88
121
/>
122
+ { renderCreateDBButton ( ) }
89
123
</ React . Fragment >
90
124
) ;
91
125
} ;
@@ -202,6 +236,53 @@ export const Tenants = ({additionalTenantsProps}: TenantsProps) => {
202
236
} ,
203
237
] ;
204
238
239
+ if ( isDeleteDBAvailable ) {
240
+ columns . push ( {
241
+ name : 'actions' ,
242
+ header : '' ,
243
+ width : 40 ,
244
+ resizeable : false ,
245
+ align : DataTable . CENTER ,
246
+ render : ( { row} ) => {
247
+ const databaseId = row . UserAttributes ?. database_id ;
248
+ const databaseName = row . Name ;
249
+
250
+ let menuItems : ( DropdownMenuItem | DropdownMenuItem [ ] ) [ ] = [ ] ;
251
+
252
+ if ( clusterName && databaseName && databaseId ) {
253
+ menuItems = [
254
+ {
255
+ text : i18n ( 'remove' ) ,
256
+ iconStart : < TrashBin /> ,
257
+ action : ( ) => {
258
+ uiFactory . onDeleteDB ?.( {
259
+ clusterName,
260
+ databaseId,
261
+ databaseName,
262
+ } ) ;
263
+ } ,
264
+ className : b ( 'remove-db' ) ,
265
+ } ,
266
+ ] ;
267
+ }
268
+
269
+ if ( ! menuItems . length ) {
270
+ return null ;
271
+ }
272
+ return (
273
+ < DropdownMenu
274
+ defaultSwitcherProps = { {
275
+ view : 'flat' ,
276
+ size : 's' ,
277
+ pin : 'brick-brick' ,
278
+ } }
279
+ items = { menuItems }
280
+ />
281
+ ) ;
282
+ } ,
283
+ } ) ;
284
+ }
285
+
205
286
if ( filteredTenants . length === 0 && problemFilter !== ProblemFilterValues . ALL ) {
206
287
return < Illustration name = "thumbsUp" width = "200" /> ;
207
288
}
@@ -218,12 +299,16 @@ export const Tenants = ({additionalTenantsProps}: TenantsProps) => {
218
299
} ;
219
300
220
301
return (
221
- < TableWithControlsLayout >
222
- < TableWithControlsLayout . Controls > { renderControls ( ) } </ TableWithControlsLayout . Controls >
223
- { error ? < ResponseError error = { error } /> : null }
224
- < TableWithControlsLayout . Table loading = { loading } >
225
- { currentData ? renderTable ( ) : null }
226
- </ TableWithControlsLayout . Table >
227
- </ TableWithControlsLayout >
302
+ < div className = { b ( 'table-wrapper' ) } >
303
+ < TableWithControlsLayout >
304
+ < TableWithControlsLayout . Controls className = { b ( 'controls' ) } >
305
+ { renderControls ( ) }
306
+ </ TableWithControlsLayout . Controls >
307
+ { error ? < ResponseError error = { error } /> : null }
308
+ < TableWithControlsLayout . Table loading = { loading } >
309
+ { currentData ? renderTable ( ) : null }
310
+ </ TableWithControlsLayout . Table >
311
+ </ TableWithControlsLayout >
312
+ </ div >
228
313
) ;
229
314
} ;
0 commit comments