import React , { memo , useCallback , useMemo , useState , useEffect } from 'react' ; import { AppMountParameters , OverlayRef } from 'kibana/public' ; import { i18n } from '@kbn/i18n' ; import { useKibana } from '../../../../kibana_react/public' ; import { VisualizeServices , VisualizeAppState , VisualizeAppStateContainer , VisualizeEditorVisInstance , } from '../types' ; import { VISUALIZE_APP_NAME } from '../../../common/constants' ; import { getTopNavConfig } from '../utils' ; import type { IndexPattern } from '../../../../data/public' ; interface VisualizeTopNavProps { currentAppState : VisualizeAppState ; isChromeVisible ? : boolean ; isEmbeddableRendered : boolean ; hasUnsavedChanges : boolean ; setHasUnsavedChanges : ( value : boolean ) => void ; hasUnappliedChanges : boolean ; originatingApp ? : string ; originatingPath ? : string ; visInstance : VisualizeEditorVisInstance ; setOriginatingApp ? : ( originatingApp : string | undefined ) => void ; stateContainer : VisualizeAppStateContainer ; visualizationIdFromUrl ? : string ; embeddableId ? : string ; onAppLeave : AppMountParameters [ 'onAppLeave' ] ; } const TopNav = ( { currentAppState , isChromeVisible , isEmbeddableRendered , hasUnsavedChanges , setHasUnsavedChanges , hasUnappliedChanges , originatingApp , setOriginatingApp , originatingPath , visInstance , stateContainer , visualizationIdFromUrl , embeddableId , onAppLeave , } ) => { const { services } = useKibana < VisualizeServices > ( ) ; const { TopNavMenu } = services . navigation . ui ; const { setHeaderActionMenu , visualizeCapabilities } = services ; const { embeddableHandler , vis } = visInstance ; const [ inspectorSession , setInspectorSession ] = useState < OverlayRef > ( ) ; const openInspector = useCallback ( ( ) => { const session = embeddableHandler . openInspector ( ) ; setInspectorSession ( session ) ; } , [ embeddableHandler ] ) ; const doReload = useCallback ( async ( ) => { services . data . search . session . start ( ) ; await visInstance . embeddableHandler . reload ( ) ; } , [ visInstance . embeddableHandler , services . data . search . session ] ) ; const handleRefresh = useCallback ( ( _payload , isUpdate ? ) => { if ( isUpdate === false ) { doReload ( ) ; } } , [ doReload ] ) ; const config = useMemo ( ( ) => { if ( isEmbeddableRendered ) { return getTopNavConfig ( { hasUnsavedChanges , setHasUnsavedChanges , hasUnappliedChanges , openInspector , originatingApp , setOriginatingApp , originatingPath , visInstance , stateContainer , visualizationIdFromUrl , stateTransfer : services . stateTransferService , embeddableId , } , services ) ; } } , [ isEmbeddableRendered , hasUnsavedChanges , setHasUnsavedChanges , hasUnappliedChanges , openInspector , originatingApp , originatingPath , visInstance , setOriginatingApp , stateContainer , visualizationIdFromUrl , services , embeddableId , ] ) ; const [ indexPatterns , setIndexPatterns ] = useState < IndexPattern [ ] > ( vis . data . indexPattern ? [ vis . data . indexPattern ] : [ ] ) ; const showDatePicker = ( ) => { const hasTimeField = vis . data . indexPattern ? ! ! vis . data . indexPattern . timeFieldName : true ; return vis . type . options . showTimePicker && hasTimeField ; } ; const showFilterBar = vis . type . options . showFilterBar ; const showQueryInput = vis . type . requiresSearch && vis . type . options . showQueryBar ; useEffect ( ( ) => { return ( ) => { if ( inspectorSession ) { inspectorSession . close ( ) ; } } ; } , [ inspectorSession ] ) ; useEffect ( ( ) => { onAppLeave ( ( actions ) => { if ( originatingApp && ( hasUnappliedChanges || hasUnsavedChanges ) && ! services . stateTransferService . isTransferInProgress ) { return actions . confirm ( i18n . translate ( 'visualizations.confirmModal.confirmTextDescription' , { defaultMessage : 'Leave Visualize editor with unsaved changes?' , } ) , i18n . translate ( 'visualizations.confirmModal.title' , { defaultMessage : 'Unsaved changes' , } ) ) ; } return actions . default ( ) ; } ) ; return ( ) => { onAppLeave ( ( actions ) => actions . default ( ) ) ; } ; } , [ onAppLeave , originatingApp , hasUnsavedChanges , hasUnappliedChanges , visualizeCapabilities . save , services . stateTransferService . isTransferInProgress , ] ) ; useEffect ( ( ) => { const asyncSetIndexPattern = async ( ) => { let indexes ; if ( vis . type . getUsedIndexPattern ) { indexes = await vis . type . getUsedIndexPattern ( vis . params ) ; } if ( ! indexes || ! indexes . length ) { const defaultIndex = await services . data . indexPatterns . getDefault ( ) ; if ( defaultIndex ) { indexes = [ defaultIndex ] ; } } if ( indexes ) { setIndexPatterns ( indexes ) ; } } ; if ( ! vis . data . indexPattern ) { asyncSetIndexPattern ( ) ; } } , [ vis . params , vis . type , services . data . indexPatterns , vis . data . indexPattern ] ) ; useEffect ( ( ) => { const autoRefreshFetchSub = services . data . query . timefilter . timefilter . getAutoRefreshFetch$ ( ) . subscribe ( async ( done ) => { try { await doReload ( ) ; } finally { done ( ) ; } } ) ; return ( ) => { autoRefreshFetchSub . unsubscribe ( ) ; } ; } , [ services . data . query . timefilter . timefilter , doReload ] ) ; return isChromeVisible ? ( < TopNavMenu appName = { VISUALIZE_APP_NAME } config = { config } setMenuMountPoint = { setHeaderActionMenu } onQuerySubmit = { handleRefresh } savedQueryId = { currentAppState . savedQuery } onSavedQueryIdChange = { stateContainer . transitions . updateSavedQuery } indexPatterns = { indexPatterns } screenTitle = { vis . title } showAutoRefreshOnly = { ! showDatePicker ( ) } showDatePicker = { showDatePicker ( ) } showFilterBar = { showFilterBar } showQueryInput = { showQueryInput } showSaveQuery = { Boolean ( services . visualizeCapabilities . saveQuery ) } showSearchBar useDefaultBehaviors />) : showFilterBar ? ( < TopNavMenu appName = { VISUALIZE_APP_NAME } setMenuMountPoint = { setHeaderActionMenu } indexPatterns = { indexPatterns } showSearchBar showSaveQuery = { false } showDatePicker = { false } showQueryInput = { false } / > ) : null ; } ; export const VisualizeTopNav = memo ( TopNav ) ;