44 * you may not use this file except in compliance with the Elastic License.
55 */
66
7- import {
8- EuiContextMenu ,
9- EuiContextMenuPanelDescriptor ,
10- EuiPopover ,
11- EuiPopoverProps ,
12- } from '@elastic/eui' ;
7+ import { EuiPopoverProps , EuiCode } from '@elastic/eui' ;
138import { i18n } from '@kbn/i18n' ;
9+ import { FormattedMessage } from '@kbn/i18n/react' ;
1410
15- import React from 'react' ;
11+ import React , { useMemo } from 'react' ;
1612import { InfraWaffleMapNode , InfraWaffleMapOptions } from '../../lib/lib' ;
1713import { getNodeDetailUrl , getNodeLogsUrl } from '../../pages/link_to' ;
1814import { createUptimeLink } from './lib/create_uptime_link' ;
19- import { findInventoryModel } from '../../../common/inventory_models' ;
15+ import { findInventoryModel , findInventoryFields } from '../../../common/inventory_models' ;
2016import { useKibana } from '../../../../../../../src/plugins/kibana_react/public' ;
2117import { InventoryItemType } from '../../../common/inventory_models/types' ;
18+ import {
19+ Section ,
20+ SectionLinkProps ,
21+ ActionMenu ,
22+ SectionTitle ,
23+ SectionSubtitle ,
24+ SectionLinks ,
25+ SectionLink ,
26+ } from '../../../../../../plugins/observability/public' ;
2227
2328interface Props {
2429 options : InfraWaffleMapOptions ;
@@ -43,83 +48,139 @@ export const NodeContextMenu = ({
4348} : Props ) => {
4449 const uiCapabilities = useKibana ( ) . services . application ?. capabilities ;
4550 const inventoryModel = findInventoryModel ( nodeType ) ;
51+ const nodeDetailFrom = currentTime - inventoryModel . metrics . defaultTimeRangeInSeconds * 1000 ;
4652 // Due to the changing nature of the fields between APM and this UI,
4753 // We need to have some exceptions until 7.0 & ECS is finalized. Reference
4854 // #26620 for the details for these fields.
4955 // TODO: This is tech debt, remove it after 7.0 & ECS migration.
5056 const apmField = nodeType === 'host' ? 'host.hostname' : inventoryModel . fields . id ;
5157
52- const nodeLogsMenuItem = {
53- name : i18n . translate ( 'xpack.infra.nodeContextMenu.viewLogsName' , {
54- defaultMessage : 'View logs' ,
58+ const showDetail = inventoryModel . crosslinkSupport . details ;
59+ const showLogsLink =
60+ inventoryModel . crosslinkSupport . logs && node . id && uiCapabilities ?. logs ?. show ;
61+ const showAPMTraceLink =
62+ inventoryModel . crosslinkSupport . apm && uiCapabilities ?. apm && uiCapabilities ?. apm . show ;
63+ const showUptimeLink =
64+ inventoryModel . crosslinkSupport . uptime && ( [ 'pod' , 'container' ] . includes ( nodeType ) || node . ip ) ;
65+
66+ const inventoryId = useMemo ( ( ) => {
67+ if ( nodeType === 'host' ) {
68+ if ( node . ip ) {
69+ return { label : < EuiCode > host.ip</ EuiCode > , value : node . ip } ;
70+ }
71+ } else {
72+ if ( options . fields ) {
73+ const { id } = findInventoryFields ( nodeType , options . fields ) ;
74+ return {
75+ label : < EuiCode > { id } </ EuiCode > ,
76+ value : node . id ,
77+ } ;
78+ }
79+ }
80+ return { label : '' , value : '' } ;
81+ } , [ nodeType , node . ip , node . id , options . fields ] ) ;
82+
83+ const nodeLogsMenuItem : SectionLinkProps = {
84+ label : i18n . translate ( 'xpack.infra.nodeContextMenu.viewLogsName' , {
85+ defaultMessage : '{inventoryName} logs' ,
86+ values : { inventoryName : inventoryModel . singularDisplayName } ,
5587 } ) ,
5688 href : getNodeLogsUrl ( {
5789 nodeType,
5890 nodeId : node . id ,
5991 time : currentTime ,
6092 } ) ,
6193 'data-test-subj' : 'viewLogsContextMenuItem' ,
94+ isDisabled : ! showLogsLink ,
6295 } ;
6396
64- const nodeDetailFrom = currentTime - inventoryModel . metrics . defaultTimeRangeInSeconds * 1000 ;
65- const nodeDetailMenuItem = {
66- name : i18n . translate ( 'xpack.infra.nodeContextMenu.viewMetricsName' , {
67- defaultMessage : 'View metrics' ,
97+ const nodeDetailMenuItem : SectionLinkProps = {
98+ label : i18n . translate ( 'xpack.infra.nodeContextMenu.viewMetricsName' , {
99+ defaultMessage : '{inventoryName} metrics' ,
100+ values : { inventoryName : inventoryModel . singularDisplayName } ,
68101 } ) ,
69102 href : getNodeDetailUrl ( {
70103 nodeType,
71104 nodeId : node . id ,
72105 from : nodeDetailFrom ,
73106 to : currentTime ,
74107 } ) ,
108+ isDisabled : ! showDetail ,
75109 } ;
76110
77- const apmTracesMenuItem = {
78- name : i18n . translate ( 'xpack.infra.nodeContextMenu.viewAPMTraces' , {
79- defaultMessage : 'View APM traces' ,
111+ const apmTracesMenuItem : SectionLinkProps = {
112+ label : i18n . translate ( 'xpack.infra.nodeContextMenu.viewAPMTraces' , {
113+ defaultMessage : '{inventoryName} APM traces' ,
114+ values : { inventoryName : inventoryModel . singularDisplayName } ,
80115 } ) ,
81116 href : `../app/apm#/traces?_g=()&kuery=${ apmField } :"${ node . id } "` ,
82117 'data-test-subj' : 'viewApmTracesContextMenuItem' ,
118+ isDisabled : ! showAPMTraceLink ,
83119 } ;
84120
85- const uptimeMenuItem = {
86- name : i18n . translate ( 'xpack.infra.nodeContextMenu.viewUptimeLink' , {
87- defaultMessage : 'View in Uptime' ,
121+ const uptimeMenuItem : SectionLinkProps = {
122+ label : i18n . translate ( 'xpack.infra.nodeContextMenu.viewUptimeLink' , {
123+ defaultMessage : '{inventoryName} in Uptime' ,
124+ values : { inventoryName : inventoryModel . singularDisplayName } ,
88125 } ) ,
89126 href : createUptimeLink ( options , nodeType , node ) ,
127+ isDisabled : ! showUptimeLink ,
90128 } ;
91129
92- const showDetail = inventoryModel . crosslinkSupport . details ;
93- const showLogsLink =
94- inventoryModel . crosslinkSupport . logs && node . id && uiCapabilities ?. logs ?. show ;
95- const showAPMTraceLink =
96- inventoryModel . crosslinkSupport . apm && uiCapabilities ?. apm && uiCapabilities ?. apm . show ;
97- const showUptimeLink =
98- inventoryModel . crosslinkSupport . uptime && ( [ 'pod' , 'container' ] . includes ( nodeType ) || node . ip ) ;
99-
100- const items = [
101- ...( showLogsLink ? [ nodeLogsMenuItem ] : [ ] ) ,
102- ...( showDetail ? [ nodeDetailMenuItem ] : [ ] ) ,
103- ...( showAPMTraceLink ? [ apmTracesMenuItem ] : [ ] ) ,
104- ...( showUptimeLink ? [ uptimeMenuItem ] : [ ] ) ,
105- ] ;
106- const panels : EuiContextMenuPanelDescriptor [ ] = [ { id : 0 , title : '' , items } ] ;
107-
108- // If there is nothing to show then we need to return the child as is
109- if ( items . length === 0 ) {
110- return < > { children } </ > ;
111- }
112-
113130 return (
114- < EuiPopover
131+ < ActionMenu
115132 closePopover = { closePopover }
116133 id = { `${ node . pathId } -popover` }
117134 isOpen = { isPopoverOpen }
118135 button = { children }
119- panelPaddingSize = "none"
120136 anchorPosition = { popoverPosition }
121137 >
122- < EuiContextMenu initialPanelId = { 0 } panels = { panels } data-test-subj = "nodeContextMenu" />
123- </ EuiPopover >
138+ < div style = { { maxWidth : 300 } } data-test-subj = "nodeContextMenu" >
139+ < Section >
140+ < SectionTitle >
141+ < FormattedMessage
142+ id = "xpack.infra.nodeContextMenu.title"
143+ defaultMessage = "{inventoryName} details"
144+ values = { { inventoryName : inventoryModel . singularDisplayName } }
145+ />
146+ </ SectionTitle >
147+ { inventoryId . label && (
148+ < SectionSubtitle >
149+ < div style = { { wordBreak : 'break-all' } } >
150+ < FormattedMessage
151+ id = "xpack.infra.nodeContextMenu.description"
152+ defaultMessage = "View details for {label} {value}"
153+ values = { { label : inventoryId . label , value : inventoryId . value } }
154+ />
155+ </ div >
156+ </ SectionSubtitle >
157+ ) }
158+ < SectionLinks >
159+ < SectionLink
160+ data-test-subj = "viewLogsContextMenuItem"
161+ label = { nodeLogsMenuItem . label }
162+ href = { nodeLogsMenuItem . href }
163+ isDisabled = { nodeLogsMenuItem . isDisabled }
164+ />
165+ < SectionLink
166+ label = { nodeDetailMenuItem . label }
167+ href = { nodeDetailMenuItem . href }
168+ isDisabled = { nodeDetailMenuItem . isDisabled }
169+ />
170+ < SectionLink
171+ label = { apmTracesMenuItem . label }
172+ href = { apmTracesMenuItem . href }
173+ data-test-subj = "viewApmTracesContextMenuItem"
174+ isDisabled = { apmTracesMenuItem . isDisabled }
175+ />
176+ < SectionLink
177+ label = { uptimeMenuItem . label }
178+ href = { uptimeMenuItem . href }
179+ isDisabled = { uptimeMenuItem . isDisabled }
180+ />
181+ </ SectionLinks >
182+ </ Section >
183+ </ div >
184+ </ ActionMenu >
124185 ) ;
125186} ;
0 commit comments