import { isEmpty , uniqueId } from 'lodash' ; import React , { createContext , useEffect , useState } from 'react' ; import { useRouteMatch } from 'react-router-dom' ; import { asyncForEach } from '@kbn/std' ; import { getDataHandler } from '../data_handler' ; import { FETCH_STATUS } from '../hooks/use_fetcher' ; import { usePluginContext } from '../hooks/use_plugin_context' ; import { useTimeRange } from '../hooks/use_time_range' ; import { getObservabilityAlerts } from '../services/get_observability_alerts' ; import { ObservabilityFetchDataPlugins } from '../typings/fetch_overview_data' ; import { ApmIndicesConfig } from '../../common/typings' ; type DataContextApps = ObservabilityFetchDataPlugins | 'alert' ; export type HasDataMap = Record < DataContextApps , { status : FETCH_STATUS ; hasData ? : boolean ; indices ? : string | ApmIndicesConfig ; serviceName ? : string ; } > ; export interface HasDataContextValue { hasDataMap : Partial < HasDataMap > ; hasAnyData ? : boolean ; isAllRequestsComplete : boolean ; onRefreshTimeRange : ( ) => void ; forceUpdate : string ; } export const HasDataContext = createContext ( { } as HasDataContextValue ) ; const apps = [ 'apm' , 'synthetics' , 'infra_logs' , 'infra_metrics' , 'ux' , 'alert' ] ; export function HasDataContextProvider ( { children } ) { const { core } = usePluginContext ( ) ; const [ forceUpdate , setForceUpdate ] = useState ( '' ) ; const { absoluteStart , absoluteEnd } = useTimeRange ( ) ; const [ hasDataMap , setHasDataMap ] = useState < HasDataContextValue [ 'hasDataMap' ] > ( { } ) ; const isExploratoryView = useRouteMatch ( '/exploratory-view' ) ; useEffect ( ( ) => { if ( ! isExploratoryView ) asyncForEach ( apps , async ( app ) => { try { const updateState = ( { hasData , indices , serviceName , } ) => { setHasDataMap ( ( prevState ) => ( { ... prevState , [ app ] : { hasData , ... ( serviceName ? { serviceName } : { } ) , ... ( indices ? { indices } : { } ) , status : FETCH_STATUS . SUCCESS , } , } ) ) ; } ; switch ( app ) { case 'ux' : const params = { absoluteTime : { start : absoluteStart , end : absoluteEnd } } ; const resultUx = await getDataHandler ( app ) ?. hasData ( params ) ; updateState ( { hasData : resultUx ?. hasData , indices : resultUx ?. indices , serviceName : resultUx ?. serviceName as string , } ) ; break ; case 'synthetics' : const resultSy = await getDataHandler ( app ) ?. hasData ( ) ; updateState ( { hasData : resultSy ?. hasData , indices : resultSy ?. indices } ) ; break ; case 'apm' : const resultApm = await getDataHandler ( app ) ?. hasData ( ) ; updateState ( { hasData : resultApm ?. hasData , indices : resultApm ?. indices } ) ; break ; case 'infra_logs' : const resultInfra = await getDataHandler ( app ) ?. hasData ( ) ; updateState ( { hasData : resultInfra } ) ; break ; case 'infra_metrics' : const resultInfraMetrics = await getDataHandler ( app ) ?. hasData ( ) ; updateState ( { hasData : resultInfraMetrics ?. hasData , indices : resultInfraMetrics ?. indices , } ) ; break ; } } catch ( e ) { setHasDataMap ( ( prevState ) => ( { ... prevState , [ app ] : { hasData : undefined , status : FETCH_STATUS . FAILURE , } , } ) ) ; } } ) ; } , [ isExploratoryView ] ) ; useEffect ( ( ) => { async function fetchAlerts ( ) { try { const alerts = await getObservabilityAlerts ( { core } ) ; setHasDataMap ( ( prevState ) => ( { ... prevState , alert : { hasData : alerts . length > 0 , status : FETCH_STATUS . SUCCESS , } , } ) ) ; } catch ( e ) { setHasDataMap ( ( prevState ) => ( { ... prevState , alert : { hasData : undefined , status : FETCH_STATUS . FAILURE , } , } ) ) ; } } fetchAlerts ( ) ; } , [ forceUpdate , core ] ) ; const isAllRequestsComplete = apps . every ( ( app ) => { const appStatus = hasDataMap [ app ] ?. status ; return appStatus !== undefined && appStatus !== FETCH_STATUS . LOADING ; } ) ; const hasAnyData = ( Object . keys ( hasDataMap ) as ObservabilityFetchDataPlugins [ ] ) . some ( ( app ) => { const appHasData = hasDataMap [ app ] ?. hasData ; return appHasData === true ; } ) ; return ( < HasDataContext . Provider value = { { hasDataMap , hasAnyData : isEmpty ( hasDataMap ) ? undefined : hasAnyData , isAllRequestsComplete , forceUpdate , onRefreshTimeRange : ( ) => { setForceUpdate ( uniqueId ( ) ) ; } , } } children = { children } / > ) ; }