@@ -290,6 +290,17 @@ const getDashboardFolderCardsForType = (type) => {
290290 const meta = dashboardTypeMeta ( type ) ;
291291 return $ ( `${ meta . tbodySelector } .folder-showcase-outer` ) ;
292292} ;
293+ const getDashboardWidgetBodyForType = ( type ) => {
294+ const meta = dashboardTypeMeta ( type ) ;
295+ return $ ( meta . tbodySelector ) . first ( ) ;
296+ } ;
297+ const getDashboardWidgetUpdatedRowForType = ( type ) => {
298+ const $tbody = getDashboardWidgetBodyForType ( type ) ;
299+ if ( ! $tbody . length ) {
300+ return $ ( ) ;
301+ }
302+ return $tbody . children ( 'tr.updated' ) . first ( ) ;
303+ } ;
293304const isDashboardNodeVisible = ( node ) => {
294305 if ( ! node || ! ( node instanceof Element ) ) {
295306 return false ;
@@ -308,7 +319,41 @@ const isDashboardNodeVisible = (node) => {
308319 }
309320 current = current . parentElement ;
310321 }
311- return node . getClientRects ( ) . length > 0 ;
322+ const rect = typeof node . getBoundingClientRect === 'function' ? node . getBoundingClientRect ( ) : null ;
323+ if ( ! rect ) {
324+ return false ;
325+ }
326+ return rect . width > 1 && rect . height > 1 ;
327+ } ;
328+ const isDashboardWidgetCollapsedForType = ( type ) => {
329+ const resolvedType = type === 'vm' ? 'vm' : 'docker' ;
330+ const $tbody = getDashboardWidgetBodyForType ( resolvedType ) ;
331+ if ( ! $tbody . length ) {
332+ return true ;
333+ }
334+ const $updatedRow = getDashboardWidgetUpdatedRowForType ( resolvedType ) ;
335+ if ( $updatedRow . length ) {
336+ const updatedNode = $updatedRow . get ( 0 ) ;
337+ const style = updatedNode ? window . getComputedStyle ( updatedNode ) : null ;
338+ if ( style && ( style . display === 'none' || style . visibility === 'hidden' ) ) {
339+ return true ;
340+ }
341+ const rect = updatedNode && typeof updatedNode . getBoundingClientRect === 'function'
342+ ? updatedNode . getBoundingClientRect ( )
343+ : null ;
344+ if ( rect && ( rect . width < 8 || rect . height < 8 ) ) {
345+ return true ;
346+ }
347+ }
348+ const $headerRow = $tbody . children ( 'tr' ) . not ( '.updated' ) . first ( ) ;
349+ const iconClass = String (
350+ $headerRow . find ( 'a.switch i, .switch i' ) . first ( ) . attr ( 'class' )
351+ || ''
352+ ) . toLowerCase ( ) ;
353+ if ( iconClass . includes ( 'angle-down' ) || iconClass . includes ( 'chevron-down' ) ) {
354+ return true ;
355+ }
356+ return false ;
312357} ;
313358const getFirstVisibleDashboardFolderCardForType = ( type ) => {
314359 const $cards = getDashboardFolderCardsForType ( type ) ;
@@ -325,7 +370,67 @@ const getFirstVisibleDashboardFolderCardForType = (type) => {
325370 } ) ;
326371 return firstVisible ;
327372} ;
373+ const ensureDashboardWidgetInlineHostMountForType = ( type , hostOverride = null ) => {
374+ const resolvedType = type === 'vm' ? 'vm' : 'docker' ;
375+ const $container = resolveDashboardWidgetInlineHostForType ( resolvedType ) ;
376+ const $host = hostOverride && hostOverride . length
377+ ? hostOverride
378+ : $ ( `.fv-dashboard-layout-inline-host[data-fv-dashboard-type="${ resolvedType } "]` ) . first ( ) ;
379+ if ( ! $container . length || ! $host . length ) {
380+ return $container ;
381+ }
382+ if ( ! $host . parent ( ) . is ( $container ) ) {
383+ $container . prepend ( $host ) ;
384+ }
385+ $container . addClass ( 'fv-dashboard-layout-inline-container' ) ;
386+ return $container ;
387+ } ;
328388const hasVisibleDashboardFolderCardsForType = ( type ) => ! ! getFirstVisibleDashboardFolderCardForType ( type ) ;
389+ const syncDashboardWidgetQuickRailFitForType = ( type , parentRect , offsetTop ) => {
390+ const resolvedType = type === 'vm' ? 'vm' : 'docker' ;
391+ const $host = $ ( `.fv-dashboard-layout-inline-host[data-fv-dashboard-type="${ resolvedType } "]` ) . first ( ) ;
392+ if ( ! $host . length ) {
393+ return ;
394+ }
395+ const $rail = $host . children ( '.fv-dashboard-layout-quick-rail' ) . first ( ) ;
396+ if ( ! $rail . length ) {
397+ return ;
398+ }
399+ const availableHeight = Math . max ( 0 , Math . floor ( ( parentRect ?. height || 0 ) - offsetTop - 2 ) ) ;
400+ if ( availableHeight <= 0 ) {
401+ $host . css ( 'max-height' , '' ) ;
402+ $rail . css ( 'max-height' , '' ) ;
403+ $rail . removeClass ( 'is-clamped is-compact-grid' ) ;
404+ return ;
405+ }
406+ $host . css ( 'max-height' , `${ availableHeight } px` ) ;
407+ $rail . css ( 'max-height' , `${ availableHeight } px` ) ;
408+
409+ const $buttons = $rail . children ( 'button.fv-dashboard-quick-action' ) ;
410+ const buttonCount = $buttons . length ;
411+ const buttonNode = $buttons . first ( ) . get ( 0 ) ;
412+ const buttonStyle = buttonNode ? window . getComputedStyle ( buttonNode ) : null ;
413+ const buttonHeight = buttonStyle
414+ ? Math . max ( 10 , Math . round ( parseFloat ( buttonStyle . height ) || 16 ) )
415+ : 16 ;
416+ const railNode = $rail . get ( 0 ) ;
417+ const railStyle = railNode ? window . getComputedStyle ( railNode ) : null ;
418+ const rowGap = railStyle
419+ ? Math . max ( 0 , Math . round ( parseFloat ( railStyle . rowGap || railStyle . gap || '2' ) || 2 ) )
420+ : 2 ;
421+ const singleRows = buttonCount ;
422+ const singleHeight = singleRows > 0
423+ ? ( singleRows * buttonHeight ) + ( Math . max ( 0 , singleRows - 1 ) * rowGap )
424+ : 0 ;
425+ const gridRows = Math . ceil ( buttonCount / 2 ) ;
426+ const gridHeight = gridRows > 0
427+ ? ( gridRows * buttonHeight ) + ( Math . max ( 0 , gridRows - 1 ) * rowGap )
428+ : 0 ;
429+ const useCompactGrid = availableHeight < singleHeight && availableHeight >= gridHeight ;
430+ $rail . toggleClass ( 'is-compact-grid' , useCompactGrid ) ;
431+ const requiredHeight = useCompactGrid ? gridHeight : singleHeight ;
432+ $rail . toggleClass ( 'is-clamped' , requiredHeight > availableHeight ) ;
433+ } ;
329434const syncDashboardWidgetQuickRailAlignmentForType = ( type ) => {
330435 const resolvedType = type === 'vm' ? 'vm' : 'docker' ;
331436 const $host = $ ( `.fv-dashboard-layout-inline-host[data-fv-dashboard-type="${ resolvedType } "]` ) . first ( ) ;
@@ -337,28 +442,37 @@ const syncDashboardWidgetQuickRailAlignmentForType = (type) => {
337442 const firstVisibleCard = getFirstVisibleDashboardFolderCardForType ( resolvedType ) ;
338443 if ( ! parentNode || ! firstVisibleCard || ! isDashboardNodeVisible ( parentNode ) ) {
339444 $host . css ( 'top' , '' ) ;
445+ $host . css ( 'max-height' , '' ) ;
446+ $host . children ( '.fv-dashboard-layout-quick-rail' ) . first ( ) . css ( 'max-height' , '' ) . removeClass ( 'is-clamped is-compact-grid' ) ;
340447 return ;
341448 }
342449 const parentRect = parentNode . getBoundingClientRect ( ) ;
343450 const cardRect = firstVisibleCard . getBoundingClientRect ( ) ;
344451 const offsetTop = Math . max ( 0 , Math . round ( cardRect . top - parentRect . top ) ) ;
345452 $host . css ( 'top' , `${ offsetTop } px` ) ;
453+ syncDashboardWidgetQuickRailFitForType ( resolvedType , parentRect , offsetTop ) ;
346454} ;
347455const syncDashboardWidgetQuickRailVisibilityForType = ( type ) => {
348456 const resolvedType = type === 'vm' ? 'vm' : 'docker' ;
349457 const $host = $ ( `.fv-dashboard-layout-inline-host[data-fv-dashboard-type="${ resolvedType } "]` ) . first ( ) ;
350458 if ( ! $host . length ) {
351459 return ;
352460 }
461+ ensureDashboardWidgetInlineHostMountForType ( resolvedType , $host ) ;
353462 const hostNode = $host . get ( 0 ) ;
354463 const parentNode = hostNode && hostNode . parentElement ? hostNode . parentElement : null ;
355464 const shouldShow = ! ! parentNode
356465 && isDashboardNodeVisible ( parentNode )
466+ && isDashboardWidgetCollapsedForType ( resolvedType ) !== true
357467 && hasVisibleDashboardFolderCardsForType ( resolvedType ) ;
358468 $host . toggleClass ( 'is-hidden' , ! shouldShow ) ;
359469 if ( shouldShow ) {
360470 syncDashboardWidgetQuickRailAlignmentForType ( resolvedType ) ;
471+ return ;
361472 }
473+ $host . css ( 'top' , '' ) ;
474+ $host . css ( 'max-height' , '' ) ;
475+ $host . children ( '.fv-dashboard-layout-quick-rail' ) . first ( ) . css ( 'max-height' , '' ) . removeClass ( 'is-clamped is-compact-grid' ) ;
362476} ;
363477const getDashboardFolderIdsForType = ( type ) => {
364478 const ids = [ ] ;
@@ -571,11 +685,8 @@ const ensureDashboardWidgetLayoutQuickSwitchForType = (type) => {
571685 let $host = $ ( hostSelector ) . first ( ) ;
572686 if ( ! $host . length ) {
573687 $host = $ ( `<div class="fv-dashboard-layout-inline-host fv-dashboard-quick-rail-host" data-fv-dashboard-type="${ resolvedType } "></div>` ) ;
574- $container . prepend ( $host ) ;
575- } else if ( ! $host . parent ( ) . is ( $container ) ) {
576- $container . prepend ( $host ) ;
577688 }
578- $container . addClass ( 'fv-dashboard-layout-inline-container' ) ;
689+ ensureDashboardWidgetInlineHostMountForType ( resolvedType , $host ) ;
579690 if ( ! $host . hasClass ( 'fv-dashboard-quick-rail-host' ) ) {
580691 $host . addClass ( 'fv-dashboard-quick-rail-host' ) ;
581692 }
@@ -872,6 +983,8 @@ const bindDashboardWidgetVisibilityObserverForType = (type) => {
872983 } ) ;
873984 }
874985 observer . observe ( containerNode , {
986+ attributes : true ,
987+ attributeFilter : [ 'class' , 'style' , 'hidden' , 'aria-hidden' ] ,
875988 childList : true ,
876989 subtree : true
877990 } ) ;
@@ -895,8 +1008,12 @@ const bindDashboardQuickActionSyncHandlers = () => {
8951008 }
8961009 } ) ;
8971010 $ ( document ) . on ( 'click.fvplusdashboardquickcollapse' , 'a.switch, .switch' , ( ) => {
1011+ scheduleDashboardWidgetVisibilitySyncForType ( 'docker' , 0 ) ;
1012+ scheduleDashboardWidgetVisibilitySyncForType ( 'vm' , 0 ) ;
8981013 scheduleDashboardWidgetVisibilitySyncForType ( 'docker' , 80 ) ;
8991014 scheduleDashboardWidgetVisibilitySyncForType ( 'vm' , 80 ) ;
1015+ scheduleDashboardWidgetVisibilitySyncForType ( 'docker' , 220 ) ;
1016+ scheduleDashboardWidgetVisibilitySyncForType ( 'vm' , 220 ) ;
9001017 } ) ;
9011018 $ ( window ) . on ( 'resize.fvplusdashboardquick orientationchange.fvplusdashboardquick' , ( ) => {
9021019 scheduleDashboardWidgetVisibilitySyncForType ( 'docker' , 0 ) ;
0 commit comments