From 7b47320070d9a104572074bd0d8134f033452c8b Mon Sep 17 00:00:00 2001 From: Phillip Burch Date: Tue, 14 Jan 2020 17:22:27 -0600 Subject: [PATCH 01/14] Create a new menu for observability links. Use it on inentory page. --- .../common/inventory_models/aws_ec2/index.ts | 3 + .../common/inventory_models/aws_rds/index.ts | 3 + .../common/inventory_models/aws_s3/index.ts | 3 + .../common/inventory_models/aws_sqs/index.ts | 3 + .../inventory_models/container/index.ts | 3 + .../common/inventory_models/host/index.ts | 3 + .../common/inventory_models/pod/index.ts | 3 + .../infra/common/inventory_models/types.ts | 1 + .../public/components/waffle/action_menu.tsx | 84 +++++++++++++++++ .../components/waffle/node_context_menu.tsx | 93 ++++++++++--------- 10 files changed, 154 insertions(+), 45 deletions(-) create mode 100644 x-pack/legacy/plugins/infra/public/components/waffle/action_menu.tsx diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/index.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/index.ts index ccfd8cd9851ebc..5f667beebd83b0 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/index.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/index.ts @@ -13,6 +13,9 @@ export const awsEC2: InventoryModel = { displayName: i18n.translate('xpack.infra.inventoryModels.awsEC2.displayName', { defaultMessage: 'EC2 Instances', }), + singularDisplayName: i18n.translate('xpack.infra.inventoryModels.awsEC2.singularDisplayName', { + defaultMessage: 'EC2 Instance', + }), requiredModule: 'aws', crosslinkSupport: { details: true, diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/index.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/index.ts index f1182a942ff061..02cef192b59efc 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/index.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/index.ts @@ -13,6 +13,9 @@ export const awsRDS: InventoryModel = { displayName: i18n.translate('xpack.infra.inventoryModels.awsRDS.displayName', { defaultMessage: 'RDS Databases', }), + singularDisplayName: i18n.translate('xpack.infra.inventoryModels.awsRDS.singularDisplayName', { + defaultMessage: 'RDS Database', + }), requiredModule: 'aws', crosslinkSupport: { details: true, diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/index.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/index.ts index 3bdf319f49c5f8..a786283a100a98 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/index.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/index.ts @@ -13,6 +13,9 @@ export const awsS3: InventoryModel = { displayName: i18n.translate('xpack.infra.inventoryModels.awsS3.displayName', { defaultMessage: 'S3 Buckets', }), + singularDisplayName: i18n.translate('xpack.infra.inventoryModels.awsS3.singularDisplayName', { + defaultMessage: 'S3 Bucket', + }), requiredModule: 'aws', crosslinkSupport: { details: true, diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/index.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/index.ts index 1733e995a824f9..21379ebb1e6045 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/index.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/index.ts @@ -13,6 +13,9 @@ export const awsSQS: InventoryModel = { displayName: i18n.translate('xpack.infra.inventoryModels.awsSQS.displayName', { defaultMessage: 'SQS Queues', }), + singularDisplayName: i18n.translate('xpack.infra.inventoryModels.awsSQS.singularDisplayName', { + defaultMessage: 'SQS Queue', + }), requiredModule: 'aws', crosslinkSupport: { details: true, diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/container/index.ts b/x-pack/legacy/plugins/infra/common/inventory_models/container/index.ts index 29b3cfe3af1804..c142f600d1d56a 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/container/index.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/container/index.ts @@ -13,6 +13,9 @@ export const container: InventoryModel = { displayName: i18n.translate('xpack.infra.inventoryModel.container.displayName', { defaultMessage: 'Docker Containers', }), + singularDisplayName: i18n.translate('xpack.infra.inventoryModel.container.singularDisplayName', { + defaultMessage: 'Docker Container', + }), requiredModule: 'docker', crosslinkSupport: { details: true, diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/host/index.ts b/x-pack/legacy/plugins/infra/common/inventory_models/host/index.ts index 364ef0b4c2c918..538af4f5119b42 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/host/index.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/host/index.ts @@ -17,6 +17,9 @@ export const host: InventoryModel = { displayName: i18n.translate('xpack.infra.inventoryModel.host.displayName', { defaultMessage: 'Hosts', }), + singularDisplayName: i18n.translate('xpack.infra.inventoryModels.host.singularDisplayName', { + defaultMessage: 'Host', + }), requiredModule: 'system', crosslinkSupport: { details: true, diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/pod/index.ts b/x-pack/legacy/plugins/infra/common/inventory_models/pod/index.ts index f76a0304e26c04..961e0248c79da9 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/pod/index.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/pod/index.ts @@ -14,6 +14,9 @@ export const pod: InventoryModel = { displayName: i18n.translate('xpack.infra.inventoryModel.pod.displayName', { defaultMessage: 'Kubernetes Pods', }), + singularDisplayName: i18n.translate('xpack.infra.inventoryModels.pod.singularDisplayName', { + defaultMessage: 'Kubernetes Pod', + }), requiredModule: 'kubernetes', crosslinkSupport: { details: true, diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/types.ts b/x-pack/legacy/plugins/infra/common/inventory_models/types.ts index cc2396547edc4b..2f61b16fb3df85 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/types.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/types.ts @@ -320,6 +320,7 @@ export interface InventoryMetrics { export interface InventoryModel { id: string; displayName: string; + singularDisplayName: string; requiredModule: string; fields: { id: string; diff --git a/x-pack/legacy/plugins/infra/public/components/waffle/action_menu.tsx b/x-pack/legacy/plugins/infra/public/components/waffle/action_menu.tsx new file mode 100644 index 00000000000000..698b7de86f1a56 --- /dev/null +++ b/x-pack/legacy/plugins/infra/public/components/waffle/action_menu.tsx @@ -0,0 +1,84 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { + EuiPopover, + EuiText, + EuiListGroup, + EuiSpacer, + EuiHorizontalRule, + PopoverAnchorPosition, +} from '@elastic/eui'; + +import React, { useCallback, ReactNode } from 'react'; +import { EuiListGroupItemProps } from '@elastic/eui/src/components/list_group/list_group_item'; + +interface Props { + sections: Section[]; + button: NonNullable; + anchorPosition?: PopoverAnchorPosition; + otherLinks?: EuiListGroupItemProps[]; + id?: string; + isOpen?: boolean; + closePopover(): void; +} + +interface Section { + title: string; + description: string; + links: EuiListGroupItemProps[]; +} + +export const ActionMenu = (props: Props) => { + const { closePopover, button, anchorPosition, isOpen, id, sections, otherLinks } = props; + + const linkWithDefaults = useCallback((link: EuiListGroupItemProps) => { + link.style = { ...link.style, padding: 0 }; + link.size = link.size || 's'; + return link; + }, []); + + return ( + + <> + {sections.map((s, idx) => ( + + +
{s.title}
+
+ + + {s.description} + + + linkWithDefaults(l))} + /> + {idx !== sections.length - 1 && } +
+ ))} + {otherLinks?.length && ( +
+ + linkWithDefaults(l))} + /> +
+ )} + +
+ ); +}; diff --git a/x-pack/legacy/plugins/infra/public/components/waffle/node_context_menu.tsx b/x-pack/legacy/plugins/infra/public/components/waffle/node_context_menu.tsx index 5a90efcc51a574..3e6eb16701ec24 100644 --- a/x-pack/legacy/plugins/infra/public/components/waffle/node_context_menu.tsx +++ b/x-pack/legacy/plugins/infra/public/components/waffle/node_context_menu.tsx @@ -4,21 +4,18 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - EuiContextMenu, - EuiContextMenuPanelDescriptor, - EuiPopover, - EuiPopoverProps, -} from '@elastic/eui'; +import { EuiPopoverProps } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React from 'react'; +import { EuiListGroupItemProps } from '@elastic/eui/src/components/list_group/list_group_item'; import { InfraWaffleMapNode, InfraWaffleMapOptions } from '../../lib/lib'; import { getNodeDetailUrl, getNodeLogsUrl } from '../../pages/link_to'; import { createUptimeLink } from './lib/create_uptime_link'; import { findInventoryModel } from '../../../common/inventory_models'; import { useKibana } from '../../../../../../../src/plugins/kibana_react/public'; import { InventoryItemType } from '../../../common/inventory_models/types'; +import { ActionMenu } from './action_menu'; interface Props { options: InfraWaffleMapOptions; @@ -43,15 +40,25 @@ export const NodeContextMenu = ({ }: Props) => { const uiCapabilities = useKibana().services.application?.capabilities; const inventoryModel = findInventoryModel(nodeType); + const nodeDetailFrom = currentTime - inventoryModel.metrics.defaultTimeRangeInSeconds * 1000; // Due to the changing nature of the fields between APM and this UI, // We need to have some exceptions until 7.0 & ECS is finalized. Reference // #26620 for the details for these fields. // TODO: This is tech debt, remove it after 7.0 & ECS migration. const apmField = nodeType === 'host' ? 'host.hostname' : inventoryModel.fields.id; - const nodeLogsMenuItem = { - name: i18n.translate('xpack.infra.nodeContextMenu.viewLogsName', { - defaultMessage: 'View logs', + const showDetail = inventoryModel.crosslinkSupport.details; + const showLogsLink = + inventoryModel.crosslinkSupport.logs && node.id && uiCapabilities?.logs?.show; + const showAPMTraceLink = + inventoryModel.crosslinkSupport.apm && uiCapabilities?.apm && uiCapabilities?.apm.show; + const showUptimeLink = + inventoryModel.crosslinkSupport.uptime && (['pod', 'container'].includes(nodeType) || node.ip); + + const nodeLogsMenuItem: EuiListGroupItemProps = { + label: i18n.translate('xpack.infra.nodeContextMenu.viewLogsName', { + defaultMessage: '{inventoryName} logs', + values: { inventoryName: inventoryModel.singularDisplayName }, }), href: getNodeLogsUrl({ nodeType, @@ -59,12 +66,13 @@ export const NodeContextMenu = ({ time: currentTime, }), 'data-test-subj': 'viewLogsContextMenuItem', + isDisabled: !showLogsLink, }; - const nodeDetailFrom = currentTime - inventoryModel.metrics.defaultTimeRangeInSeconds * 1000; - const nodeDetailMenuItem = { - name: i18n.translate('xpack.infra.nodeContextMenu.viewMetricsName', { - defaultMessage: 'View metrics', + const nodeDetailMenuItem: EuiListGroupItemProps = { + label: i18n.translate('xpack.infra.nodeContextMenu.viewMetricsName', { + defaultMessage: '{inventoryName} metrics', + values: { inventoryName: inventoryModel.singularDisplayName }, }), href: getNodeDetailUrl({ nodeType, @@ -72,54 +80,49 @@ export const NodeContextMenu = ({ from: nodeDetailFrom, to: currentTime, }), + isDisabled: !showDetail, }; - const apmTracesMenuItem = { - name: i18n.translate('xpack.infra.nodeContextMenu.viewAPMTraces', { - defaultMessage: 'View APM traces', + const apmTracesMenuItem: EuiListGroupItemProps = { + label: i18n.translate('xpack.infra.nodeContextMenu.viewAPMTraces', { + defaultMessage: '{inventoryName} APM traces', + values: { inventoryName: inventoryModel.singularDisplayName }, }), href: `../app/apm#/traces?_g=()&kuery=${apmField}:"${node.id}"`, 'data-test-subj': 'viewApmTracesContextMenuItem', + isDisabled: !showAPMTraceLink, }; - const uptimeMenuItem = { - name: i18n.translate('xpack.infra.nodeContextMenu.viewUptimeLink', { - defaultMessage: 'View in Uptime', + const uptimeMenuItem: EuiListGroupItemProps = { + label: i18n.translate('xpack.infra.nodeContextMenu.viewUptimeLink', { + defaultMessage: '{inventoryName} in Uptime', + values: { inventoryName: inventoryModel.singularDisplayName }, }), href: createUptimeLink(options, nodeType, node), + isDisabled: !showUptimeLink, }; - const showDetail = inventoryModel.crosslinkSupport.details; - const showLogsLink = - inventoryModel.crosslinkSupport.logs && node.id && uiCapabilities?.logs?.show; - const showAPMTraceLink = - inventoryModel.crosslinkSupport.apm && uiCapabilities?.apm && uiCapabilities?.apm.show; - const showUptimeLink = - inventoryModel.crosslinkSupport.uptime && (['pod', 'container'].includes(nodeType) || node.ip); - - const items = [ - ...(showLogsLink ? [nodeLogsMenuItem] : []), - ...(showDetail ? [nodeDetailMenuItem] : []), - ...(showAPMTraceLink ? [apmTracesMenuItem] : []), - ...(showUptimeLink ? [uptimeMenuItem] : []), - ]; - const panels: EuiContextMenuPanelDescriptor[] = [{ id: 0, title: '', items }]; - - // If there is nothing to show then we need to return the child as is - if (items.length === 0) { - return <>{children}; - } - return ( - - - + /> ); }; From 185b024e2cbc41ecc6ffd2d6c585bc8266d7b77c Mon Sep 17 00:00:00 2001 From: Phillip Burch Date: Tue, 14 Jan 2020 17:37:12 -0600 Subject: [PATCH 02/14] Change the order of props for clarity --- .../plugins/infra/public/components/waffle/action_menu.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/legacy/plugins/infra/public/components/waffle/action_menu.tsx b/x-pack/legacy/plugins/infra/public/components/waffle/action_menu.tsx index 698b7de86f1a56..ec2b28ebeae6b5 100644 --- a/x-pack/legacy/plugins/infra/public/components/waffle/action_menu.tsx +++ b/x-pack/legacy/plugins/infra/public/components/waffle/action_menu.tsx @@ -18,9 +18,10 @@ import { EuiListGroupItemProps } from '@elastic/eui/src/components/list_group/li interface Props { sections: Section[]; + otherLinks?: EuiListGroupItemProps[]; + button: NonNullable; anchorPosition?: PopoverAnchorPosition; - otherLinks?: EuiListGroupItemProps[]; id?: string; isOpen?: boolean; closePopover(): void; From f3f07f5fd0631eee14f9a72c058a3518788d68ff Mon Sep 17 00:00:00 2001 From: Phillip Burch Date: Tue, 14 Jan 2020 18:09:17 -0600 Subject: [PATCH 03/14] Fix default message --- .../infra/public/components/waffle/node_context_menu.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/legacy/plugins/infra/public/components/waffle/node_context_menu.tsx b/x-pack/legacy/plugins/infra/public/components/waffle/node_context_menu.tsx index 3e6eb16701ec24..b67b8cda1524b4 100644 --- a/x-pack/legacy/plugins/infra/public/components/waffle/node_context_menu.tsx +++ b/x-pack/legacy/plugins/infra/public/components/waffle/node_context_menu.tsx @@ -107,7 +107,7 @@ export const NodeContextMenu = ({ sections={[ { title: i18n.translate('xpack.infra.nodeContextMenu.title', { - defaultMessage: `${inventoryModel.singularDisplayName} details`, + defaultMessage: '{inventoryName} details', values: { inventoryName: inventoryModel.singularDisplayName }, }), description: i18n.translate('xpack.infra.nodeContextMenu.description', { From 6c94d9f476a69fdcc9e3c4ccec82f9171160d445 Mon Sep 17 00:00:00 2001 From: Phillip Burch Date: Tue, 21 Jan 2020 13:47:36 -0600 Subject: [PATCH 04/14] Composition over configuration --- .../public/components/waffle/action_menu.tsx | 99 +++++++------------ .../components/waffle/node_context_menu.tsx | 67 ++++++++++--- 2 files changed, 86 insertions(+), 80 deletions(-) diff --git a/x-pack/legacy/plugins/infra/public/components/waffle/action_menu.tsx b/x-pack/legacy/plugins/infra/public/components/waffle/action_menu.tsx index ec2b28ebeae6b5..69097369e4c0d4 100644 --- a/x-pack/legacy/plugins/infra/public/components/waffle/action_menu.tsx +++ b/x-pack/legacy/plugins/infra/public/components/waffle/action_menu.tsx @@ -10,76 +10,47 @@ import { EuiListGroup, EuiSpacer, EuiHorizontalRule, - PopoverAnchorPosition, + EuiListGroupItem, + EuiPopoverProps, } from '@elastic/eui'; -import React, { useCallback, ReactNode } from 'react'; +import React, { HTMLAttributes } from 'react'; import { EuiListGroupItemProps } from '@elastic/eui/src/components/list_group/list_group_item'; -interface Props { - sections: Section[]; - otherLinks?: EuiListGroupItemProps[]; +type Props = EuiPopoverProps & HTMLAttributes; - button: NonNullable; - anchorPosition?: PopoverAnchorPosition; - id?: string; - isOpen?: boolean; - closePopover(): void; -} +export const SectionTitle: React.FC<{}> = props => ( + <> + +
{props.children}
+
+ + +); -interface Section { - title: string; - description: string; - links: EuiListGroupItemProps[]; -} +export const SectionSubtitle: React.FC<{}> = props => ( + <> + + {props.children} + + + +); -export const ActionMenu = (props: Props) => { - const { closePopover, button, anchorPosition, isOpen, id, sections, otherLinks } = props; +export const SectionLinks: React.FC<{}> = props => ( + + {props.children} + +); - const linkWithDefaults = useCallback((link: EuiListGroupItemProps) => { - link.style = { ...link.style, padding: 0 }; - link.size = link.size || 's'; - return link; - }, []); +export const SectionSpacer: React.FC<{}> = () => ; - return ( - - <> - {sections.map((s, idx) => ( - - -
{s.title}
-
- - - {s.description} - - - linkWithDefaults(l))} - /> - {idx !== sections.length - 1 && } -
- ))} - {otherLinks?.length && ( -
- - linkWithDefaults(l))} - /> -
- )} - -
- ); -}; +export const Section: React.FC<{}> = props => <>{props.children}; + +export const SectionLink: React.FC = props => ( + +); + +export const ActionMenuDivider: React.FC<{}> = props => ; + +export const ActionMenu: React.FC = props => ; diff --git a/x-pack/legacy/plugins/infra/public/components/waffle/node_context_menu.tsx b/x-pack/legacy/plugins/infra/public/components/waffle/node_context_menu.tsx index b67b8cda1524b4..cb4bbf9f4def2d 100644 --- a/x-pack/legacy/plugins/infra/public/components/waffle/node_context_menu.tsx +++ b/x-pack/legacy/plugins/infra/public/components/waffle/node_context_menu.tsx @@ -6,6 +6,7 @@ import { EuiPopoverProps } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; import React from 'react'; import { EuiListGroupItemProps } from '@elastic/eui/src/components/list_group/list_group_item'; @@ -15,7 +16,14 @@ import { createUptimeLink } from './lib/create_uptime_link'; import { findInventoryModel } from '../../../common/inventory_models'; import { useKibana } from '../../../../../../../src/plugins/kibana_react/public'; import { InventoryItemType } from '../../../common/inventory_models/types'; -import { ActionMenu } from './action_menu'; +import { + ActionMenu, + Section, + SectionTitle, + SectionSubtitle, + SectionLinks, + SectionLink, +} from './action_menu'; interface Props { options: InfraWaffleMapOptions; @@ -104,25 +112,52 @@ export const NodeContextMenu = ({ return ( + > +
+ + + + + + + + + + + + +
+
); }; From 6b942e7d2b5f841150de0a3f5e3c61287d80288d Mon Sep 17 00:00:00 2001 From: Phillip Burch Date: Wed, 22 Jan 2020 13:56:58 -0600 Subject: [PATCH 05/14] Show ids and ips. PR feedback. --- .../public/components/waffle/action_menu.tsx | 3 +- .../components/waffle/node_context_menu.tsx | 52 +++++++++++++------ 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/x-pack/legacy/plugins/infra/public/components/waffle/action_menu.tsx b/x-pack/legacy/plugins/infra/public/components/waffle/action_menu.tsx index 69097369e4c0d4..6e964dde3aecf7 100644 --- a/x-pack/legacy/plugins/infra/public/components/waffle/action_menu.tsx +++ b/x-pack/legacy/plugins/infra/public/components/waffle/action_menu.tsx @@ -47,10 +47,11 @@ export const SectionSpacer: React.FC<{}> = () => ; export const Section: React.FC<{}> = props => <>{props.children}; +export type SectionLinkProps = EuiListGroupItemProps; export const SectionLink: React.FC = props => ( ); export const ActionMenuDivider: React.FC<{}> = props => ; -export const ActionMenu: React.FC = props => ; +export const ActionMenu: React.FC = props => ; diff --git a/x-pack/legacy/plugins/infra/public/components/waffle/node_context_menu.tsx b/x-pack/legacy/plugins/infra/public/components/waffle/node_context_menu.tsx index cb4bbf9f4def2d..27f4f5cb91ce1a 100644 --- a/x-pack/legacy/plugins/infra/public/components/waffle/node_context_menu.tsx +++ b/x-pack/legacy/plugins/infra/public/components/waffle/node_context_menu.tsx @@ -4,12 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ -import { EuiPopoverProps } from '@elastic/eui'; +import { EuiPopoverProps, EuiCode } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import React from 'react'; -import { EuiListGroupItemProps } from '@elastic/eui/src/components/list_group/list_group_item'; +import React, { useMemo } from 'react'; import { InfraWaffleMapNode, InfraWaffleMapOptions } from '../../lib/lib'; import { getNodeDetailUrl, getNodeLogsUrl } from '../../pages/link_to'; import { createUptimeLink } from './lib/create_uptime_link'; @@ -23,6 +22,7 @@ import { SectionSubtitle, SectionLinks, SectionLink, + SectionLinkProps, } from './action_menu'; interface Props { @@ -63,7 +63,27 @@ export const NodeContextMenu = ({ const showUptimeLink = inventoryModel.crosslinkSupport.uptime && (['pod', 'container'].includes(nodeType) || node.ip); - const nodeLogsMenuItem: EuiListGroupItemProps = { + const inventoryId = useMemo(() => { + switch (nodeType) { + case 'host': + if (node.ip) { + return { label: host.ip, value: node.ip }; + } else { + return { label: '', value: '' }; + } + case 'pod': + return { label: pod.uid, value: node.id }; + case 'container': + return { label: container.id, value: node.id }; + case 'awsEC2': + case 'awsRDS': + case 'awsSQS': + case 'awsS3': + return { label: instance.id, value: node.id }; + } + }, [nodeType, node]); + + const nodeLogsMenuItem: SectionLinkProps = { label: i18n.translate('xpack.infra.nodeContextMenu.viewLogsName', { defaultMessage: '{inventoryName} logs', values: { inventoryName: inventoryModel.singularDisplayName }, @@ -77,7 +97,7 @@ export const NodeContextMenu = ({ isDisabled: !showLogsLink, }; - const nodeDetailMenuItem: EuiListGroupItemProps = { + const nodeDetailMenuItem: SectionLinkProps = { label: i18n.translate('xpack.infra.nodeContextMenu.viewMetricsName', { defaultMessage: '{inventoryName} metrics', values: { inventoryName: inventoryModel.singularDisplayName }, @@ -91,7 +111,7 @@ export const NodeContextMenu = ({ isDisabled: !showDetail, }; - const apmTracesMenuItem: EuiListGroupItemProps = { + const apmTracesMenuItem: SectionLinkProps = { label: i18n.translate('xpack.infra.nodeContextMenu.viewAPMTraces', { defaultMessage: '{inventoryName} APM traces', values: { inventoryName: inventoryModel.singularDisplayName }, @@ -101,7 +121,7 @@ export const NodeContextMenu = ({ isDisabled: !showAPMTraceLink, }; - const uptimeMenuItem: EuiListGroupItemProps = { + const uptimeMenuItem: SectionLinkProps = { label: i18n.translate('xpack.infra.nodeContextMenu.viewUptimeLink', { defaultMessage: '{inventoryName} in Uptime', values: { inventoryName: inventoryModel.singularDisplayName }, @@ -126,15 +146,15 @@ export const NodeContextMenu = ({ values={{ inventoryName: inventoryModel.singularDisplayName }} /> - - - + {inventoryId.label && ( + + + + )} Date: Thu, 23 Jan 2020 11:38:04 -0600 Subject: [PATCH 06/14] Don't wrap subtitle. Use fields in inventory model for name --- .../public/components/waffle/action_menu.tsx | 7 +- .../components/waffle/node_context_menu.tsx | 110 +++++++++--------- 2 files changed, 60 insertions(+), 57 deletions(-) diff --git a/x-pack/legacy/plugins/infra/public/components/waffle/action_menu.tsx b/x-pack/legacy/plugins/infra/public/components/waffle/action_menu.tsx index 6e964dde3aecf7..cff78760364570 100644 --- a/x-pack/legacy/plugins/infra/public/components/waffle/action_menu.tsx +++ b/x-pack/legacy/plugins/infra/public/components/waffle/action_menu.tsx @@ -30,7 +30,12 @@ export const SectionTitle: React.FC<{}> = props => ( export const SectionSubtitle: React.FC<{}> = props => ( <> - + {props.children} diff --git a/x-pack/legacy/plugins/infra/public/components/waffle/node_context_menu.tsx b/x-pack/legacy/plugins/infra/public/components/waffle/node_context_menu.tsx index 27f4f5cb91ce1a..3dea88bce96b49 100644 --- a/x-pack/legacy/plugins/infra/public/components/waffle/node_context_menu.tsx +++ b/x-pack/legacy/plugins/infra/public/components/waffle/node_context_menu.tsx @@ -12,7 +12,7 @@ import React, { useMemo } from 'react'; import { InfraWaffleMapNode, InfraWaffleMapOptions } from '../../lib/lib'; import { getNodeDetailUrl, getNodeLogsUrl } from '../../pages/link_to'; import { createUptimeLink } from './lib/create_uptime_link'; -import { findInventoryModel } from '../../../common/inventory_models'; +import { findInventoryModel, findInventoryFields } from '../../../common/inventory_models'; import { useKibana } from '../../../../../../../src/plugins/kibana_react/public'; import { InventoryItemType } from '../../../common/inventory_models/types'; import { @@ -64,24 +64,20 @@ export const NodeContextMenu = ({ inventoryModel.crosslinkSupport.uptime && (['pod', 'container'].includes(nodeType) || node.ip); const inventoryId = useMemo(() => { - switch (nodeType) { - case 'host': - if (node.ip) { - return { label: host.ip, value: node.ip }; - } else { - return { label: '', value: '' }; - } - case 'pod': - return { label: pod.uid, value: node.id }; - case 'container': - return { label: container.id, value: node.id }; - case 'awsEC2': - case 'awsRDS': - case 'awsSQS': - case 'awsS3': - return { label: instance.id, value: node.id }; + if (nodeType === 'host') { + if (node.ip) { + return { label: host.ip, value: node.ip }; + } + } else { + if (options.fields) { + return { + label: {findInventoryFields(nodeType, options.fields).id}, + value: node.id, + }; + } } - }, [nodeType, node]); + return { label: '', value: '' }; + }, [nodeType, node.ip, node.id, options.fields]); const nodeLogsMenuItem: SectionLinkProps = { label: i18n.translate('xpack.infra.nodeContextMenu.viewLogsName', { @@ -138,46 +134,48 @@ export const NodeContextMenu = ({ button={children} anchorPosition={popoverPosition} > -
- - - - {inventoryId.label && ( - +
+
+ - - )} - - - - - - -
+ + {inventoryId.label && ( + + + + )} + + + + + + +
+ ); }; From 6bc748cf591dc21bc2e22952440c446c2eed1e45 Mon Sep 17 00:00:00 2001 From: Phillip Burch Date: Thu, 23 Jan 2020 16:34:45 -0600 Subject: [PATCH 07/14] Tooltip was becoming hacky. Keep it simple and wrap the id. --- .../public/components/waffle/action_menu.tsx | 7 +------ .../components/waffle/node_context_menu.tsx | 17 ++++++++++------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/x-pack/legacy/plugins/infra/public/components/waffle/action_menu.tsx b/x-pack/legacy/plugins/infra/public/components/waffle/action_menu.tsx index cff78760364570..6e964dde3aecf7 100644 --- a/x-pack/legacy/plugins/infra/public/components/waffle/action_menu.tsx +++ b/x-pack/legacy/plugins/infra/public/components/waffle/action_menu.tsx @@ -30,12 +30,7 @@ export const SectionTitle: React.FC<{}> = props => ( export const SectionSubtitle: React.FC<{}> = props => ( <> - + {props.children} diff --git a/x-pack/legacy/plugins/infra/public/components/waffle/node_context_menu.tsx b/x-pack/legacy/plugins/infra/public/components/waffle/node_context_menu.tsx index 3dea88bce96b49..eb9e601cd9361c 100644 --- a/x-pack/legacy/plugins/infra/public/components/waffle/node_context_menu.tsx +++ b/x-pack/legacy/plugins/infra/public/components/waffle/node_context_menu.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { EuiPopoverProps, EuiCode } from '@elastic/eui'; +import { EuiPopoverProps, EuiCode, EuiToolTip } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; @@ -70,8 +70,9 @@ export const NodeContextMenu = ({ } } else { if (options.fields) { + const { id } = findInventoryFields(nodeType, options.fields); return { - label: {findInventoryFields(nodeType, options.fields).id}, + label: {id}, value: node.id, }; } @@ -145,11 +146,13 @@ export const NodeContextMenu = ({ {inventoryId.label && ( - +
+ +
)} From 2efb21221320fb712227e92341bdea98df52a81b Mon Sep 17 00:00:00 2001 From: Phillip Burch Date: Fri, 24 Jan 2020 14:50:32 -0600 Subject: [PATCH 08/14] Create observability plugin. Add action menu to it. --- .../components/waffle/node_context_menu.tsx | 8 ++++---- x-pack/plugins/observability/kibana.json | 6 ++++++ .../public/components}/action_menu.tsx | 0 x-pack/plugins/observability/public/index.ts | 16 ++++++++++++++++ x-pack/plugins/observability/public/plugin.ts | 15 +++++++++++++++ 5 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 x-pack/plugins/observability/kibana.json rename x-pack/{legacy/plugins/infra/public/components/waffle => plugins/observability/public/components}/action_menu.tsx (100%) create mode 100644 x-pack/plugins/observability/public/index.ts create mode 100644 x-pack/plugins/observability/public/plugin.ts diff --git a/x-pack/legacy/plugins/infra/public/components/waffle/node_context_menu.tsx b/x-pack/legacy/plugins/infra/public/components/waffle/node_context_menu.tsx index eb9e601cd9361c..b4426e9e798df0 100644 --- a/x-pack/legacy/plugins/infra/public/components/waffle/node_context_menu.tsx +++ b/x-pack/legacy/plugins/infra/public/components/waffle/node_context_menu.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { EuiPopoverProps, EuiCode, EuiToolTip } from '@elastic/eui'; +import { EuiPopoverProps, EuiCode } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; @@ -16,14 +16,14 @@ import { findInventoryModel, findInventoryFields } from '../../../common/invento import { useKibana } from '../../../../../../../src/plugins/kibana_react/public'; import { InventoryItemType } from '../../../common/inventory_models/types'; import { - ActionMenu, Section, + SectionLinkProps, + ActionMenu, SectionTitle, SectionSubtitle, SectionLinks, SectionLink, - SectionLinkProps, -} from './action_menu'; +} from '../../../../../../../x-pack/plugins/observability/public'; interface Props { options: InfraWaffleMapOptions; diff --git a/x-pack/plugins/observability/kibana.json b/x-pack/plugins/observability/kibana.json new file mode 100644 index 00000000000000..57063ea729ed6d --- /dev/null +++ b/x-pack/plugins/observability/kibana.json @@ -0,0 +1,6 @@ +{ + "id": "observability", + "version": "8.0.0", + "kibanaVersion": "kibana", + "ui": true +} diff --git a/x-pack/legacy/plugins/infra/public/components/waffle/action_menu.tsx b/x-pack/plugins/observability/public/components/action_menu.tsx similarity index 100% rename from x-pack/legacy/plugins/infra/public/components/waffle/action_menu.tsx rename to x-pack/plugins/observability/public/components/action_menu.tsx diff --git a/x-pack/plugins/observability/public/index.ts b/x-pack/plugins/observability/public/index.ts new file mode 100644 index 00000000000000..c822edc3f4de8a --- /dev/null +++ b/x-pack/plugins/observability/public/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { PluginInitializerContext, PluginInitializer } from 'kibana/public'; +import { Plugin, ClientSetup, ClientStart } from './plugin'; + +export const plugin: PluginInitializer = ( + context: PluginInitializerContext +) => { + return new Plugin(context); +}; + +export * from './components/action_menu'; diff --git a/x-pack/plugins/observability/public/plugin.ts b/x-pack/plugins/observability/public/plugin.ts new file mode 100644 index 00000000000000..a7eb1c50a03928 --- /dev/null +++ b/x-pack/plugins/observability/public/plugin.ts @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { Plugin as PluginClass, PluginInitializerContext } from 'kibana/public'; + +export type ClientSetup = void; +export type ClientStart = void; + +export class Plugin implements PluginClass { + constructor(context: PluginInitializerContext) {} + start() {} + setup() {} +} From 5eebed9245917be9531491c38ddad909d43a20f6 Mon Sep 17 00:00:00 2001 From: Phillip Burch Date: Fri, 24 Jan 2020 14:59:32 -0600 Subject: [PATCH 09/14] Fix path --- .../infra/public/components/waffle/node_context_menu.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/legacy/plugins/infra/public/components/waffle/node_context_menu.tsx b/x-pack/legacy/plugins/infra/public/components/waffle/node_context_menu.tsx index b4426e9e798df0..8bf4861113140d 100644 --- a/x-pack/legacy/plugins/infra/public/components/waffle/node_context_menu.tsx +++ b/x-pack/legacy/plugins/infra/public/components/waffle/node_context_menu.tsx @@ -23,7 +23,7 @@ import { SectionSubtitle, SectionLinks, SectionLink, -} from '../../../../../../../x-pack/plugins/observability/public'; +} from '../../../../../../plugins/observability/public'; interface Props { options: InfraWaffleMapOptions; From a082b207411720cb360495bce1922f08acc27b58 Mon Sep 17 00:00:00 2001 From: Phillip Burch Date: Mon, 27 Jan 2020 11:30:40 -0600 Subject: [PATCH 10/14] Satisfy linter and fix test --- .../public/components/waffle/node_context_menu.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/x-pack/legacy/plugins/infra/public/components/waffle/node_context_menu.tsx b/x-pack/legacy/plugins/infra/public/components/waffle/node_context_menu.tsx index 8bf4861113140d..6f0c8ea43e2328 100644 --- a/x-pack/legacy/plugins/infra/public/components/waffle/node_context_menu.tsx +++ b/x-pack/legacy/plugins/infra/public/components/waffle/node_context_menu.tsx @@ -135,12 +135,12 @@ export const NodeContextMenu = ({ button={children} anchorPosition={popoverPosition} > -
+
@@ -148,8 +148,8 @@ export const NodeContextMenu = ({
From 4caf93c7f090d161e52b27f6ea4355e74875f5a4 Mon Sep 17 00:00:00 2001 From: Phillip Burch Date: Mon, 27 Jan 2020 13:00:33 -0600 Subject: [PATCH 11/14] Please the linter --- .../infra/public/components/waffle/node_context_menu.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/x-pack/legacy/plugins/infra/public/components/waffle/node_context_menu.tsx b/x-pack/legacy/plugins/infra/public/components/waffle/node_context_menu.tsx index 6f0c8ea43e2328..86a22c358b4d51 100644 --- a/x-pack/legacy/plugins/infra/public/components/waffle/node_context_menu.tsx +++ b/x-pack/legacy/plugins/infra/public/components/waffle/node_context_menu.tsx @@ -150,13 +150,14 @@ export const NodeContextMenu = ({
)} Date: Mon, 27 Jan 2020 13:06:47 -0600 Subject: [PATCH 12/14] Update translastions --- x-pack/plugins/translations/translations/ja-JP.json | 4 +--- x-pack/plugins/translations/translations/zh-CN.json | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index b4c85f369519d4..82e15e52f50d67 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -6637,8 +6637,6 @@ "xpack.infra.metricsExplorer.openInTSVB": "ビジュアライザーで開く", "xpack.infra.metricsExplorer.viewNodeDetail": "{name} のメトリックを表示", "xpack.infra.node.ariaLabel": "{nodeName}、クリックしてメニューを開きます", - "xpack.infra.nodeContextMenu.viewLogsName": "ログを表示", - "xpack.infra.nodeContextMenu.viewMetricsName": "メトリックを表示", "xpack.infra.nodeDetails.labels.availabilityZone": "アベイラビリティゾーン", "xpack.infra.nodeDetails.labels.cloudProvider": "クラウドプロバイダー", "xpack.infra.nodeDetails.labels.containerized": "コンテナー化", @@ -13204,4 +13202,4 @@ "xpack.watcher.watchEdit.thresholdWatchExpression.aggType.fieldIsRequiredValidationMessage": "フィールドを選択してください。", "xpack.watcher.watcherDescription": "アラートの作成、管理、監視によりデータへの変更を検知します。" } -} +} \ No newline at end of file diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 583f181e148c6e..42b7e2df73cea5 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -6636,8 +6636,6 @@ "xpack.infra.metricsExplorer.openInTSVB": "在 Visualize 中打开", "xpack.infra.metricsExplorer.viewNodeDetail": "查看 {name} 的指标", "xpack.infra.node.ariaLabel": "{nodeName},单击打开菜单", - "xpack.infra.nodeContextMenu.viewLogsName": "查看日志", - "xpack.infra.nodeContextMenu.viewMetricsName": "查看指标", "xpack.infra.nodeDetails.labels.availabilityZone": "可用区", "xpack.infra.nodeDetails.labels.cloudProvider": "云服务提供商", "xpack.infra.nodeDetails.labels.containerized": "容器化", @@ -13203,4 +13201,4 @@ "xpack.watcher.watchEdit.thresholdWatchExpression.aggType.fieldIsRequiredValidationMessage": "此字段必填。", "xpack.watcher.watcherDescription": "通过创建、管理和监测警报来检测数据中的更改。" } -} +} \ No newline at end of file From 85c8f636f6e6810c82e2b3dac3b8929354ff354d Mon Sep 17 00:00:00 2001 From: Phillip Burch Date: Mon, 27 Jan 2020 14:41:52 -0600 Subject: [PATCH 13/14] Update test for disabled links --- .../apps/infra/feature_controls/infrastructure_security.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/x-pack/test/functional/apps/infra/feature_controls/infrastructure_security.ts b/x-pack/test/functional/apps/infra/feature_controls/infrastructure_security.ts index b7c5667a575065..fb37d8151de1a2 100644 --- a/x-pack/test/functional/apps/infra/feature_controls/infrastructure_security.ts +++ b/x-pack/test/functional/apps/infra/feature_controls/infrastructure_security.ts @@ -104,12 +104,14 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { it(`does not show link to view logs`, async () => { await retry.waitFor('context menu', () => testSubjects.exists('~nodeContextMenu')); - await testSubjects.missingOrFail('~viewLogsContextMenuItem'); + const link = await testSubjects.find('~viewLogsContextMenuItem'); + expect(await link.isEnabled()).to.be(false); }); it(`does not show link to view apm traces`, async () => { await retry.waitFor('context menu', () => testSubjects.exists('~nodeContextMenu')); - await testSubjects.missingOrFail('~viewApmTracesContextMenuItem'); + const link = await testSubjects.find('~viewApmTracesContextMenuItem'); + expect(await link.isEnabled()).to.be(false); }); }); From 0bc5de04c6f068043c2f1b5488cbcb89793693b5 Mon Sep 17 00:00:00 2001 From: Phillip Burch Date: Mon, 27 Jan 2020 15:49:46 -0600 Subject: [PATCH 14/14] Update more tests --- .../apps/infra/feature_controls/infrastructure_security.ts | 6 ++++-- .../apps/infra/feature_controls/infrastructure_spaces.ts | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/x-pack/test/functional/apps/infra/feature_controls/infrastructure_security.ts b/x-pack/test/functional/apps/infra/feature_controls/infrastructure_security.ts index fb37d8151de1a2..ac7bd66d3466f0 100644 --- a/x-pack/test/functional/apps/infra/feature_controls/infrastructure_security.ts +++ b/x-pack/test/functional/apps/infra/feature_controls/infrastructure_security.ts @@ -219,12 +219,14 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { it(`does not show link to view logs`, async () => { await retry.waitFor('context menu', () => testSubjects.exists('~nodeContextMenu')); - await testSubjects.missingOrFail('~viewLogsContextMenuItem'); + const link = await testSubjects.find('~viewLogsContextMenuItem'); + expect(await link.isEnabled()).to.be(false); }); it(`does not show link to view apm traces`, async () => { await retry.waitFor('context menu', () => testSubjects.exists('~nodeContextMenu')); - await testSubjects.missingOrFail('~viewApmTracesContextMenuItem'); + const link = await testSubjects.find('~viewApmTracesContextMenuItem'); + expect(await link.isEnabled()).to.be(false); }); }); diff --git a/x-pack/test/functional/apps/infra/feature_controls/infrastructure_spaces.ts b/x-pack/test/functional/apps/infra/feature_controls/infrastructure_spaces.ts index 90458ef53dfc28..1d7ef9bea81e63 100644 --- a/x-pack/test/functional/apps/infra/feature_controls/infrastructure_spaces.ts +++ b/x-pack/test/functional/apps/infra/feature_controls/infrastructure_spaces.ts @@ -191,7 +191,8 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { it(`doesn't show link to view logs`, async () => { await retry.waitFor('context menu', () => testSubjects.exists('~nodeContextMenu')); - await testSubjects.missingOrFail('~viewLogsContextMenuItem'); + const link = await testSubjects.find('~viewLogsContextMenuItem'); + expect(await link.isEnabled()).to.be(false); }); it(`shows link to view apm traces`, async () => { @@ -239,7 +240,8 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { it(`doesn't show link to view apm traces`, async () => { await retry.waitFor('context menu', () => testSubjects.exists('~nodeContextMenu')); - await testSubjects.missingOrFail('~viewApmTracesContextMenuItem'); + const link = await testSubjects.find('~viewApmTracesContextMenuItem'); + expect(await link.isEnabled()).to.be(false); }); }); });