import { EuiFlexGroup , EuiFlexItem , EuiLoadingSpinner , EuiPanel , } from '@elastic/eui' ; import React , { ReactNode } from 'react' ; import { isActivePlatinumLicense } from '../../../../common/license_check' ; import { invalidLicenseMessage , SERVICE_MAP_TIMEOUT_ERROR , } from '../../../../common/service_map' ; import { FETCH_STATUS , useFetcher } from '../../../hooks/use_fetcher' ; import { useLicenseContext } from '../../../context/license/use_license_context' ; import { useTheme } from '../../../hooks/use_theme' ; import { LicensePrompt } from '../../shared/license_prompt' ; import { Controls } from './Controls' ; import { Cytoscape } from './Cytoscape' ; import { getCytoscapeDivStyle } from './cytoscape_options' ; import { EmptyBanner } from './EmptyBanner' ; import { EmptyPrompt } from './empty_prompt' ; import { Popover } from './Popover' ; import { TimeoutPrompt } from './timeout_prompt' ; import { useRefDimensions } from './useRefDimensions' ; import { SearchBar } from '../../shared/search_bar' ; import { useServiceName } from '../../../hooks/use_service_name' ; import { useApmParams } from '../../../hooks/use_apm_params' ; import { Environment } from '../../../../common/environment_rt' ; import { useTimeRange } from '../../../hooks/use_time_range' ; function PromptContainer ( { children } ) { return ( < > < SearchBar showKueryBar = { false } / > < EuiFlexGroup alignItems = "center" justifyContent = "spaceAround" style = { { height : '60vh' } } > < EuiFlexItem grow = { false } style = { { width : 600 , textAlign : 'center' as const } } > { children } < /EuiFlexItem> < /EuiFlexGroup> < />); } function LoadingSpinner ( ) { return ( < EuiLoadingSpinner size = "xl" style = { { position : 'absolute' , top : '50%' , left : '50%' } } />); } export function ServiceMapHome ( ) { const { query : { environment , kuery , rangeFrom , rangeTo } , } = useApmParams ( '/service-map' ) ; const { start , end } = useTimeRange ( { rangeFrom , rangeTo } ) ; return ( < ServiceMap environment = { environment } kuery = { kuery } start = { start } end = { end } / > ) ; } export function ServiceMapServiceDetail ( ) { const { query : { environment , kuery , rangeFrom , rangeTo } , } = useApmParams ( '/services/{serviceName}/service-map' ) ; const { start , end } = useTimeRange ( { rangeFrom , rangeTo } ) ; return ( < ServiceMap environment = { environment } kuery = { kuery } start = { start } end = { end } / > ) ; } export function ServiceMap ( { environment , kuery , start , end , } ) { const theme = useTheme ( ) ; const license = useLicenseContext ( ) ; const serviceName = useServiceName ( ) ; const { data = { elements : [ ] } , status , error , } = useFetcher ( ( callApmApi ) => { if ( ! license || ! isActivePlatinumLicense ( license ) ) { return ; } return callApmApi ( { isCachable : false , endpoint : 'GET /internal/apm/service-map' , params : { query : { start , end , environment , serviceName , } , } , } ) ; } , [ license , serviceName , environment , start , end ] ) ; const { ref , height } = useRefDimensions ( ) ; const PADDING_BOTTOM = 24 ; const heightWithPadding = height - PADDING_BOTTOM ; if ( ! license ) { return null ; } if ( ! isActivePlatinumLicense ( license ) ) { return ( < PromptContainer > < LicensePrompt text = { invalidLicenseMessage } / > < /PromptContainer>); } if ( status === FETCH_STATUS . SUCCESS && data . elements . length === 0 ) { return ( < PromptContainer > < EmptyPrompt /> < /PromptContainer>); } if ( status === FETCH_STATUS . FAILURE && error && 'body' in error && error . body ?. statusCode === 500 && error . body ?. message === SERVICE_MAP_TIMEOUT_ERROR ) { return ( < PromptContainer > < TimeoutPrompt isGlobalServiceMap = { ! serviceName } /> < /PromptContainer>); } return ( < > < SearchBar showKueryBar = { false } showTimeComparison / > < EuiPanel hasBorder = { true } paddingSize = "none" > < div data - test - subj = "ServiceMap" style = { { height : heightWithPadding } } ref = { ref } > < Cytoscape elements = { data . elements } height = { heightWithPadding } serviceName = { serviceName } style = { getCytoscapeDivStyle ( theme , status ) } > < Controls /> { serviceName && < EmptyBanner />} { status === FETCH_STATUS . LOADING && < LoadingSpinner />} < Popover focusedServiceName = { serviceName } environment = { environment } kuery = { kuery } start = { start } end = { end } / > < /Cytoscape> < /div> < /EuiPanel> < />); }