1
- import React , { useMemo } from 'react' ;
1
+ import React , { useCallback , useMemo } from 'react' ;
2
2
import { connect } from 'react-redux' ;
3
3
import {
4
4
useHoverState ,
@@ -14,6 +14,9 @@ import {
14
14
PerformanceSignals ,
15
15
Placeholder ,
16
16
ContentWithFallback ,
17
+ palette ,
18
+ useDarkMode ,
19
+ Tooltip ,
17
20
} from '@mongodb-js/compass-components' ;
18
21
import { usePreference , withPreferences } from 'compass-preferences-model' ;
19
22
import type { ItemAction } from '@mongodb-js/compass-components' ;
@@ -117,17 +120,31 @@ const navigationItemLabel = css({
117
120
marginLeft : spacing [ 2 ] ,
118
121
} ) ;
119
122
123
+ const navigationItemDisabledDarkModeStyles = css ( {
124
+ '--item-color' : palette . gray . dark1 ,
125
+ '--item-color-active' : palette . gray . dark1 ,
126
+ '--item-bg-color-hover' : 'var(--item-bg-color)' ,
127
+ } ) ;
128
+
129
+ const navigationItemDisabledLightModeStyles = css ( {
130
+ '--item-color' : palette . gray . base ,
131
+ '--item-color-active' : palette . gray . base ,
132
+ '--item-bg-color-hover' : 'var(--item-bg-color)' ,
133
+ } ) ;
134
+
120
135
const navigationItemActionIcons = css ( { color : 'inherit' } ) ;
121
136
122
137
export function NavigationItem < Actions extends string > ( {
123
138
isExpanded,
124
139
onAction,
125
- onClick,
140
+ onClick : onButtonClick ,
126
141
glyph,
127
142
label,
128
143
actions,
129
144
isActive,
130
145
showTooManyCollectionsInsight,
146
+ disabled : isButtonDisabled = false ,
147
+ disabledMessage : buttonDisabledMessage ,
131
148
} : {
132
149
isExpanded ?: boolean ;
133
150
onAction ( actionName : Actions , ...rest : any [ ] ) : void ;
@@ -137,17 +154,35 @@ export function NavigationItem<Actions extends string>({
137
154
actions ?: ItemAction < Actions > [ ] ;
138
155
isActive : boolean ;
139
156
showTooManyCollectionsInsight ?: boolean ;
157
+ disabled ?: boolean ;
158
+ disabledMessage ?: string ;
140
159
} ) {
160
+ const darkMode = useDarkMode ( ) ;
141
161
const showInsights = usePreference ( 'showInsights' , React ) ;
162
+ const onClick = useCallback ( ( ) => {
163
+ if ( isButtonDisabled ) {
164
+ return ;
165
+ }
166
+ onButtonClick ( ) ;
167
+ } , [ isButtonDisabled , onButtonClick ] ) ;
142
168
const [ hoverProps ] = useHoverState ( ) ;
143
169
const focusRingProps = useFocusRing ( ) ;
144
170
const defaultActionProps = useDefaultAction ( onClick ) ;
145
171
146
172
const navigationItemProps = mergeProps (
147
173
{
148
- className : cx ( navigationItem , isActive && activeNavigationItem ) ,
174
+ className : cx (
175
+ navigationItem ,
176
+ isActive && activeNavigationItem ,
177
+ isButtonDisabled &&
178
+ ( darkMode
179
+ ? navigationItemDisabledDarkModeStyles
180
+ : navigationItemDisabledLightModeStyles )
181
+ ) ,
182
+ role : 'button' ,
149
183
[ 'aria-label' ] : label ,
150
184
[ 'aria-current' ] : isActive ,
185
+ [ 'aria-disabled' ] : isButtonDisabled ,
151
186
tabIndex : 0 ,
152
187
} ,
153
188
hoverProps ,
@@ -156,37 +191,52 @@ export function NavigationItem<Actions extends string>({
156
191
) as React . HTMLProps < HTMLDivElement > ;
157
192
158
193
return (
159
- < div { ...navigationItemProps } >
160
- < div className = { itemWrapper } >
161
- < div className = { itemButtonWrapper } >
162
- < Icon glyph = { glyph } size = "small" > </ Icon >
163
- { isExpanded && < span className = { navigationItemLabel } > { label } </ span > }
164
- </ div >
165
- { showInsights && isExpanded && showTooManyCollectionsInsight && (
166
- < div className = { signalContainerStyles } >
167
- < SignalPopover
168
- signals = { PerformanceSignals . get ( 'too-many-collections' ) }
169
- > </ SignalPopover >
194
+ < Tooltip
195
+ align = "right"
196
+ spacing = { spacing [ 3 ] }
197
+ isDisabled = { ! isButtonDisabled || ! buttonDisabledMessage }
198
+ trigger = { ( { children : tooltip , ...triggerProps } ) => {
199
+ const props = mergeProps ( triggerProps , navigationItemProps ) ;
200
+ return (
201
+ < div { ...props } >
202
+ < div className = { itemWrapper } >
203
+ < div className = { itemButtonWrapper } >
204
+ < Icon glyph = { glyph } size = "small" > </ Icon >
205
+ { isExpanded && (
206
+ < span className = { navigationItemLabel } > { label } </ span >
207
+ ) }
208
+ { tooltip }
209
+ </ div >
210
+ { showInsights && isExpanded && showTooManyCollectionsInsight && (
211
+ < div className = { signalContainerStyles } >
212
+ < SignalPopover
213
+ signals = { PerformanceSignals . get ( 'too-many-collections' ) }
214
+ > </ SignalPopover >
215
+ </ div >
216
+ ) }
217
+ { ! isButtonDisabled && isExpanded && actions && (
218
+ < ItemActionControls < Actions >
219
+ iconSize = "small"
220
+ onAction = { onAction }
221
+ data-testid = "sidebar-navigation-item-actions"
222
+ actions = { actions }
223
+ // This is what renders the "create database" action,
224
+ // the icons here should always be clearly visible,
225
+ // so we let the icon to inherit the foreground color of
226
+ // the text
227
+ isVisible = { true }
228
+ iconClassName = { navigationItemActionIcons }
229
+ collapseToMenuThreshold = { 3 }
230
+ > </ ItemActionControls >
231
+ ) }
232
+ < div className = { cx ( 'item-background' , itemBackground ) } />
233
+ </ div >
170
234
</ div >
171
- ) }
172
- { isExpanded && actions && (
173
- < ItemActionControls < Actions >
174
- iconSize = "small"
175
- onAction = { onAction }
176
- data-testid = "sidebar-navigation-item-actions"
177
- actions = { actions }
178
- // This is what renders the "create database" action,
179
- // the icons here should always be clearly visible,
180
- // so we let the icon to inherit the foreground color of
181
- // the text
182
- isVisible = { true }
183
- iconClassName = { navigationItemActionIcons }
184
- collapseToMenuThreshold = { 3 }
185
- > </ ItemActionControls >
186
- ) }
187
- < div className = { cx ( 'item-background' , itemBackground ) } />
188
- </ div >
189
- </ div >
235
+ ) ;
236
+ } }
237
+ >
238
+ { buttonDisabledMessage }
239
+ </ Tooltip >
190
240
) ;
191
241
}
192
242
@@ -201,8 +251,8 @@ const PlaceholderItem = ({ forLabel }: { forLabel: string }) => {
201
251
export function NavigationItems ( {
202
252
isReady,
203
253
isExpanded,
204
- showCreateDatabaseAction = false ,
205
- showPerformanceItem = false ,
254
+ showCreateDatabaseAction,
255
+ isPerformanceTabSupported ,
206
256
onFilterChange,
207
257
onAction,
208
258
currentLocation,
@@ -211,8 +261,8 @@ export function NavigationItems({
211
261
} : {
212
262
isReady ?: boolean ;
213
263
isExpanded ?: boolean ;
214
- showCreateDatabaseAction ? : boolean ;
215
- showPerformanceItem ? : boolean ;
264
+ showCreateDatabaseAction : boolean ;
265
+ isPerformanceTabSupported : boolean ;
216
266
onFilterChange ( regex : RegExp | null ) : void ;
217
267
onAction ( actionName : string , ...rest : any [ ] ) : void ;
218
268
currentLocation : string | null ;
@@ -272,16 +322,16 @@ export function NavigationItems({
272
322
label = "My Queries"
273
323
isActive = { currentLocation === 'My Queries' }
274
324
/>
275
- { showPerformanceItem && (
276
- < NavigationItem < '' >
277
- isExpanded = { isExpanded }
278
- onAction = { onAction }
279
- onClick = { openPerformanceWorkspace }
280
- glyph = "Gauge "
281
- label = " Performance"
282
- isActive = { currentLocation === 'Performance' }
283
- />
284
- ) }
325
+ < NavigationItem < '' >
326
+ isExpanded = { isExpanded }
327
+ onAction = { onAction }
328
+ onClick = { openPerformanceWorkspace }
329
+ glyph = "Gauge"
330
+ label = "Performance "
331
+ isActive = { currentLocation === ' Performance' }
332
+ disabled = { ! isPerformanceTabSupported }
333
+ disabledMessage = "Performance metrics are not available for your deployment or to your database user"
334
+ />
285
335
< NavigationItem < DatabasesActions >
286
336
isExpanded = { isExpanded }
287
337
onAction = { onAction }
@@ -321,9 +371,10 @@ const mapStateToProps = (
321
371
0
322
372
) ;
323
373
324
- const isReady = [ 'ready' , 'refreshing' ] . includes (
325
- state . instance ?. status ?? ''
326
- ) ;
374
+ const isReady =
375
+ [ 'ready' , 'refreshing' ] . includes ( state . instance ?. status ?? '' ) &&
376
+ state . isPerformanceTabSupported !== null ;
377
+
327
378
const isDataLake = state . instance ?. dataLake . isDataLake ?? false ;
328
379
const isWritable = state . instance ?. isWritable ?? false ;
329
380
@@ -332,6 +383,7 @@ const mapStateToProps = (
332
383
showPerformanceItem : ! isDataLake ,
333
384
showCreateDatabaseAction : ! isDataLake && isWritable && ! preferencesReadOnly ,
334
385
showTooManyCollectionsInsight : totalCollectionsCount > 10_000 ,
386
+ isPerformanceTabSupported : ! isDataLake && ! ! state . isPerformanceTabSupported ,
335
387
} ;
336
388
} ;
337
389
0 commit comments