@@ -20,18 +20,15 @@ import {
20
20
import React , { lazy , Suspense , useEffect , useState } from 'react' ;
21
21
import type { FC } from 'react' ;
22
22
23
- import type { Capabilities , ScopedHistory } from '@kbn/core/public' ;
23
+ import type { ScopedHistory } from '@kbn/core/public' ;
24
24
import type { FeaturesPluginStart , KibanaFeature } from '@kbn/features-plugin/public' ;
25
25
import { FormattedMessage } from '@kbn/i18n-react' ;
26
26
import { reactRouterNavigate } from '@kbn/kibana-react-plugin/public' ;
27
27
import type { Role } from '@kbn/security-plugin-types-common' ;
28
28
29
29
import { TAB_ID_CONTENT , TAB_ID_GENERAL , TAB_ID_ROLES } from './constants' ;
30
30
import { useTabs } from './hooks/use_tabs' ;
31
- import {
32
- ViewSpaceContextProvider ,
33
- type ViewSpaceServices ,
34
- } from './hooks/view_space_context_provider' ;
31
+ import { useViewSpaceServices , useViewSpaceStore } from './provider' ;
35
32
import { addSpaceIdToPath , ENTER_SPACE_PATH , type Space } from '../../../common' ;
36
33
import { getSpaceAvatarComponent } from '../../space_avatar' ;
37
34
import { SpaceSolutionBadge } from '../../space_solution_badge' ;
@@ -49,11 +46,10 @@ const getSelectedTabId = (canUserViewRoles: boolean, selectedTabId?: string) =>
49
46
: TAB_ID_GENERAL ;
50
47
} ;
51
48
52
- interface PageProps extends ViewSpaceServices {
49
+ interface PageProps {
53
50
spaceId ?: string ;
54
51
history : ScopedHistory ;
55
52
selectedTabId ?: string ;
56
- capabilities : Capabilities ;
57
53
getFeatures : FeaturesPluginStart [ 'getFeatures' ] ;
58
54
onLoadSpace : ( space : Space ) => void ;
59
55
allowFeatureVisibility : boolean ;
@@ -68,32 +64,30 @@ const handleApiError = (error: Error) => {
68
64
69
65
// FIXME: rename to EditSpacePage
70
66
// FIXME: add eventTracker
71
- export const ViewSpacePage : FC < PageProps > = ( props ) => {
72
- const {
73
- spaceId,
74
- getFeatures,
75
- spacesManager,
76
- history,
77
- onLoadSpace,
78
- selectedTabId : _selectedTabId ,
79
- capabilities,
80
- getUrlForApp,
81
- navigateToUrl,
82
- ...viewSpaceServices
83
- } = props ;
84
-
67
+ export const ViewSpace : FC < PageProps > = ( {
68
+ spaceId,
69
+ getFeatures,
70
+ history,
71
+ onLoadSpace,
72
+ selectedTabId : _selectedTabId ,
73
+ ...props
74
+ } ) => {
75
+ const { state, dispatch } = useViewSpaceStore ( ) ;
76
+ const { invokeClient } = useViewSpaceServices ( ) ;
77
+ const { spacesManager, capabilities, serverBasePath } = useViewSpaceServices ( ) ;
85
78
const [ space , setSpace ] = useState < Space | null > ( null ) ;
86
79
const [ userActiveSpace , setUserActiveSpace ] = useState < Space | null > ( null ) ;
87
80
const [ features , setFeatures ] = useState < KibanaFeature [ ] | null > ( null ) ;
88
- const [ roles , setRoles ] = useState < Role [ ] > ( [ ] ) ;
89
81
const [ isLoadingSpace , setIsLoadingSpace ] = useState ( true ) ;
90
82
const [ isLoadingFeatures , setIsLoadingFeatures ] = useState ( true ) ;
91
83
const [ isLoadingRoles , setIsLoadingRoles ] = useState ( true ) ;
92
84
const selectedTabId = getSelectedTabId ( Boolean ( capabilities ?. roles ?. view ) , _selectedTabId ) ;
93
85
const [ tabs , selectedTabContent ] = useTabs ( {
94
86
space,
95
87
features,
96
- roles,
88
+ rolesCount : state . roles . size ,
89
+ capabilities,
90
+ history,
97
91
currentSelectedTabId : selectedTabId ,
98
92
...props ,
99
93
} ) ;
@@ -123,33 +117,38 @@ export const ViewSpacePage: FC<PageProps> = (props) => {
123
117
}
124
118
125
119
const getRoles = async ( ) => {
126
- let result : Role [ ] = [ ] ;
127
- try {
128
- result = await spacesManager . getRolesForSpace ( spaceId ) ;
129
- } catch ( error ) {
130
- const message = error ?. body ?. message ?? error . toString ( ) ;
131
- const statusCode = error ?. body ?. statusCode ?? null ;
132
- if ( statusCode === 403 ) {
133
- // eslint-disable-next-line no-console
134
- console . log ( 'Insufficient permissions to get list of roles for the space' ) ;
135
- // eslint-disable-next-line no-console
136
- console . log ( message ) ;
137
- } else {
138
- // eslint-disable-next-line no-console
139
- console . error ( 'Encountered error while getting list of roles for space!' ) ;
140
- // eslint-disable-next-line no-console
141
- console . error ( error ) ;
142
- throw error ;
120
+ await invokeClient ( async ( clients ) => {
121
+ let result : Role [ ] = [ ] ;
122
+ try {
123
+ result = await clients . spacesManager . getRolesForSpace ( spaceId ) ;
124
+
125
+ dispatch ( { type : 'update_roles' , payload : result } ) ;
126
+ } catch ( error ) {
127
+ const message = error ?. body ?. message ?? error . toString ( ) ;
128
+ const statusCode = error ?. body ?. statusCode ?? null ;
129
+ if ( statusCode === 403 ) {
130
+ // eslint-disable-next-line no-console
131
+ console . log ( 'Insufficient permissions to get list of roles for the space' ) ;
132
+ // eslint-disable-next-line no-console
133
+ console . log ( message ) ;
134
+ } else {
135
+ // eslint-disable-next-line no-console
136
+ console . error ( 'Encountered error while getting list of roles for space!' ) ;
137
+ // eslint-disable-next-line no-console
138
+ console . error ( error ) ;
139
+ throw error ;
140
+ }
143
141
}
144
- }
142
+ } ) ;
145
143
146
- setRoles ( result ) ;
147
144
setIsLoadingRoles ( false ) ;
148
145
} ;
149
146
150
- // maybe we do not make this call if user can't view roles? 🤔
151
- getRoles ( ) . catch ( handleApiError ) ;
152
- } , [ spaceId , spacesManager ] ) ;
147
+ if ( ! state . roles . size ) {
148
+ // maybe we do not make this call if user can't view roles? 🤔
149
+ getRoles ( ) . catch ( handleApiError ) ;
150
+ }
151
+ } , [ dispatch , invokeClient , spaceId , state . roles ] ) ;
153
152
154
153
useEffect ( ( ) => {
155
154
const _getFeatures = async ( ) => {
@@ -194,98 +193,90 @@ export const ViewSpacePage: FC<PageProps> = (props) => {
194
193
195
194
return (
196
195
< div data-test-subj = "spaces-view-page" >
197
- < ViewSpaceContextProvider
198
- capabilities = { capabilities }
199
- spacesManager = { spacesManager }
200
- navigateToUrl = { navigateToUrl }
201
- getUrlForApp = { getUrlForApp }
202
- { ...viewSpaceServices }
203
- >
204
- < EuiText >
205
- < EuiFlexGroup data-test-subj = "spaceDetailsHeader" alignItems = "flexStart" >
206
- < EuiFlexItem grow = { false } >
207
- < HeaderAvatar />
208
- </ EuiFlexItem >
209
- < EuiFlexItem grow = { true } >
210
- < EuiTitle size = "l" >
211
- < h1 data-test-subj = "spaceTitle" >
212
- { space . name }
213
- { shouldShowSolutionBadge ? (
214
- < >
215
- { ' ' }
216
- < SpaceSolutionBadge
217
- solution = { solution }
218
- data-test-subj = { `space-solution-badge-${ solution } ` }
196
+ < EuiText >
197
+ < EuiFlexGroup data-test-subj = "spaceDetailsHeader" alignItems = "flexStart" >
198
+ < EuiFlexItem grow = { false } >
199
+ < HeaderAvatar />
200
+ </ EuiFlexItem >
201
+ < EuiFlexItem grow = { true } >
202
+ < EuiTitle size = "l" >
203
+ < h1 data-test-subj = "spaceTitle" >
204
+ { space . name }
205
+ { shouldShowSolutionBadge ? (
206
+ < >
207
+ { ' ' }
208
+ < SpaceSolutionBadge
209
+ solution = { solution }
210
+ data-test-subj = { `space-solution-badge-${ solution } ` }
211
+ />
212
+ </ >
213
+ ) : null }
214
+ { userActiveSpace ?. id === id ? (
215
+ < >
216
+ { ' ' }
217
+ < EuiBadge color = "primary" >
218
+ < FormattedMessage
219
+ id = "xpack.spaces.management.spaceDetails.space.badge.isCurrent"
220
+ description = "Text for a badge shown in the Space details page when the particular Space currently active."
221
+ defaultMessage = "Current"
219
222
/>
220
- </ >
221
- ) : null }
222
- { userActiveSpace ?. id === id ? (
223
- < >
224
- { ' ' }
225
- < EuiBadge color = "primary" >
226
- < FormattedMessage
227
- id = "xpack.spaces.management.spaceDetails.space.badge.isCurrent"
228
- description = "Text for a badge shown in the Space details page when the particular Space currently active."
229
- defaultMessage = "Current"
230
- />
231
- </ EuiBadge >
232
- </ >
233
- ) : null }
234
- </ h1 >
235
- </ EuiTitle >
223
+ </ EuiBadge >
224
+ </ >
225
+ ) : null }
226
+ </ h1 >
227
+ </ EuiTitle >
236
228
237
- < EuiText size = "s" >
238
- < p >
239
- { space . description ?? (
240
- < FormattedMessage
241
- id = "xpack.spaces.management.spaceDetails.space.description"
242
- defaultMessage = "Organize your saved objects and show related features for creating new content."
243
- />
244
- ) }
245
- </ p >
246
- </ EuiText >
247
- </ EuiFlexItem >
248
- { userActiveSpace ?. id !== id ? (
249
- < EuiFlexItem grow = { false } >
250
- < EuiButton
251
- iconType = "merge"
252
- href = { addSpaceIdToPath (
253
- props . serverBasePath ,
254
- id ,
255
- `${ ENTER_SPACE_PATH } ?next=/app/management/kibana/spaces/edit/${ id } `
256
- ) }
257
- data-test-subj = "spaceSwitcherButton"
258
- >
229
+ < EuiText size = "s" >
230
+ < p >
231
+ { space . description ?? (
259
232
< FormattedMessage
260
- id = "xpack.spaces.management.spaceDetails.space.switchToSpaceButton.label "
261
- defaultMessage = "Switch to this space "
233
+ id = "xpack.spaces.management.spaceDetails.space.description "
234
+ defaultMessage = "Organize your saved objects and show related features for creating new content. "
262
235
/>
263
- </ EuiButton >
264
- </ EuiFlexItem >
265
- ) : null }
266
- </ EuiFlexGroup >
236
+ ) }
237
+ </ p >
238
+ </ EuiText >
239
+ </ EuiFlexItem >
240
+ { userActiveSpace ?. id !== id ? (
241
+ < EuiFlexItem grow = { false } >
242
+ < EuiButton
243
+ iconType = "merge"
244
+ href = { addSpaceIdToPath (
245
+ serverBasePath ,
246
+ id ,
247
+ `${ ENTER_SPACE_PATH } ?next=/app/management/kibana/spaces/edit/${ id } `
248
+ ) }
249
+ data-test-subj = "spaceSwitcherButton"
250
+ >
251
+ < FormattedMessage
252
+ id = "xpack.spaces.management.spaceDetails.space.switchToSpaceButton.label"
253
+ defaultMessage = "Switch to this space"
254
+ />
255
+ </ EuiButton >
256
+ </ EuiFlexItem >
257
+ ) : null }
258
+ </ EuiFlexGroup >
267
259
268
- < EuiSpacer />
260
+ < EuiSpacer />
269
261
270
- < EuiFlexGroup direction = "column" >
271
- < EuiFlexItem >
272
- < EuiTabs >
273
- { tabs . map ( ( tab , index ) => (
274
- < EuiTab
275
- key = { index }
276
- isSelected = { tab . id === selectedTabId }
277
- append = { tab . append }
278
- { ...reactRouterNavigate ( history , `/edit/${ encodeURIComponent ( id ) } /${ tab . id } ` ) }
279
- >
280
- { tab . name }
281
- </ EuiTab >
282
- ) ) }
283
- </ EuiTabs >
284
- </ EuiFlexItem >
285
- < EuiFlexItem > { selectedTabContent ?? null } </ EuiFlexItem >
286
- </ EuiFlexGroup >
287
- </ EuiText >
288
- </ ViewSpaceContextProvider >
262
+ < EuiFlexGroup direction = "column" >
263
+ < EuiFlexItem >
264
+ < EuiTabs >
265
+ { tabs . map ( ( tab , index ) => (
266
+ < EuiTab
267
+ key = { index }
268
+ isSelected = { tab . id === selectedTabId }
269
+ append = { tab . append }
270
+ { ...reactRouterNavigate ( history , `/edit/${ encodeURIComponent ( id ) } /${ tab . id } ` ) }
271
+ >
272
+ { tab . name }
273
+ </ EuiTab >
274
+ ) ) }
275
+ </ EuiTabs >
276
+ </ EuiFlexItem >
277
+ < EuiFlexItem > { selectedTabContent ?? null } </ EuiFlexItem >
278
+ </ EuiFlexGroup >
279
+ </ EuiText >
289
280
</ div >
290
281
) ;
291
282
} ;
0 commit comments