import { SavedObjectsClientContract } from 'kibana/public' ; import { useEffect , useState } from 'react' ; import { useHistory , useLocation , useParams } from 'react-router-dom' ; import { i18n } from '@kbn/i18n' ; import { CoreStart } from 'kibana/public' ; import { GraphStore } from '../state_management' ; import { GraphWorkspaceSavedObject , IndexPatternSavedObject , Workspace } from '../types' ; import { getEmptyWorkspace , getSavedWorkspace } from './saved_workspace_utils' ; import { getEditUrl } from '../services/url' ; import { SpacesApi } from '../../../spaces/public' ; export interface UseWorkspaceLoaderProps { store : GraphStore ; workspaceRef : React . MutableRefObject < Workspace | undefined > ; savedObjectsClient : SavedObjectsClientContract ; coreStart : CoreStart ; spaces ? : SpacesApi ; } interface WorkspaceUrlParams { id ? : string ; } export interface SharingSavedObjectProps { outcome ? : 'aliasMatch' | 'exactMatch' | 'conflict' ; aliasTargetId ? : string ; } interface WorkspaceLoadedState { savedWorkspace : GraphWorkspaceSavedObject ; indexPatterns : IndexPatternSavedObject [ ] ; sharingSavedObjectProps ? : SharingSavedObjectProps ; } export const useWorkspaceLoader = ( { coreStart , spaces , workspaceRef , store , savedObjectsClient , } ) => { const [ state , setState ] = useState < WorkspaceLoadedState > ( ) ; const { replace : historyReplace } = useHistory ( ) ; const { search } = useLocation ( ) ; const { id } = useParams < WorkspaceUrlParams > ( ) ; /**
     * The following effect initializes workspace initially and reacts
     * on changes in id parameter and URL query only.
     */ useEffect ( ( ) => { const urlQuery = new URLSearchParams ( search ) . get ( 'query' ) ; function loadWorkspace ( fetchedSavedWorkspace , fetchedIndexPatterns ) { store . dispatch ( { type : 'x-pack/graph/LOAD_WORKSPACE' , payload : { savedWorkspace : fetchedSavedWorkspace , indexPatterns : fetchedIndexPatterns , urlQuery , } , } ) ; } function clearStore ( ) { store . dispatch ( { type : 'x-pack/graph/RESET' } ) ; } async function * pageThroughIndexPatterns ( ) { let perPage = 1000 ; let total = 0 ; let savedObjects = [ ] ; async function * makeRequest ( page ) { await savedObjectsClient . find < { title : string ; } > ( { type : 'index-pattern' , fields : [ 'title' , 'type' ] , perPage , page , } ) . then ( ( response ) => { perPage = response . perPage ; total = response . total ; savedObjects = response . savedObjects ; } ) ; yield savedObjects ; if ( total > page * perPage ) { yield * makeRequest ( ++ page ) ; } } yield * makeRequest ( 1 ) ; } async function fetchIndexPatterns ( ) { const result = pageThroughIndexPatterns ( ) ; let fetchedIndexPatterns = [ ] ; for await ( const page of result ) { fetchedIndexPatterns = fetchedIndexPatterns . concat ( page ) ; } return fetchedIndexPatterns ; } async function fetchSavedWorkspace ( ) { return id ? await getSavedWorkspace ( savedObjectsClient , id ) . catch ( function ( e ) { coreStart . notifications . toasts . addError ( e , { title : i18n . translate ( 'xpack.graph.missingWorkspaceErrorMessage' , { defaultMessage : "Couldn't load graph with ID" , } ) , } ) ; historyReplace ( '/home' ) ; return new Promise ( ( ) => { } ) ; } ) : getEmptyWorkspace ( ) ; } async function initializeWorkspace ( ) { const fetchedIndexPatterns = await fetchIndexPatterns ( ) ; const { savedObject : fetchedSavedWorkspace , sharingSavedObjectProps : fetchedSharingSavedObjectProps , } = await fetchSavedWorkspace ( ) ; if ( spaces && fetchedSharingSavedObjectProps ?. outcome === 'aliasMatch' ) { const newObjectId = fetchedSharingSavedObjectProps ?. aliasTargetId ! ; const newPath = getEditUrl ( coreStart . http . basePath . prepend , { id : newObjectId } ) + search ; spaces . ui . redirectLegacyUrl ( newPath , i18n . translate ( 'xpack.graph.legacyUrlConflict.objectNoun' , { defaultMessage : 'Graph' , } ) ) ; return null ; } /**
             * Deal with situation of request to open saved workspace. Otherwise clean up store,
             * when navigating to a new workspace from existing one.
             */ if ( fetchedSavedWorkspace . id ) { loadWorkspace ( fetchedSavedWorkspace , fetchedIndexPatterns ) ; } else if ( workspaceRef . current ) { clearStore ( ) ; } setState ( { savedWorkspace : fetchedSavedWorkspace , indexPatterns : fetchedIndexPatterns , sharingSavedObjectProps : fetchedSharingSavedObjectProps , } ) ; } initializeWorkspace ( ) ; } , [ id , search , store , historyReplace , savedObjectsClient , setState , coreStart , workspaceRef , spaces , ] ) ; return state ; } ;