From 42de8c858995b190f35858b2798f7ea4dfcb2439 Mon Sep 17 00:00:00 2001 From: Irene Blanco Date: Thu, 24 Oct 2024 16:34:55 +0200 Subject: [PATCH] [APM]Refactor ServiceTabEmptyState to use AddDataPanel (#197578) ## Summary Closes https://github.com/elastic/kibana/issues/195876 This PR refactors the ServiceTabEmptyState component to use the newly created generic AddDataPanel component, which was derived from it. The functionality remains the same. ### Tabs |Light|Dark| |-|-| |![callout_light](https://github.com/user-attachments/assets/46c7d14b-c4f4-44e4-a753-099abec378e4)|![callout_dark](https://github.com/user-attachments/assets/298386bf-eb76-4b23-9952-df6576032f86)| ### Actions ![callout_actions](https://github.com/user-attachments/assets/08c4364c-c3cb-45af-b02e-5012cbf86536) ### Dismiss ![callout_dismissable](https://github.com/user-attachments/assets/a0276001-98a9-47b3-83c9-aaa0685c7418) --- .../components/app/service_overview/index.tsx | 2 +- .../app/service_tab_empty_state/constants.ts | 229 ++++++++++++------ .../app/service_tab_empty_state/index.tsx | 162 +++---------- .../entities_inventory_callout.tsx | 6 +- .../templates/apm_main_template/index.tsx | 2 +- .../add_metrics_callout/index.tsx | 2 +- .../add_data_panel/add_data_panel.stories.tsx | 4 +- .../components/add_data_panel/index.tsx | 8 +- 8 files changed, 196 insertions(+), 219 deletions(-) diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/service_overview/index.tsx b/x-pack/plugins/observability_solution/apm/public/components/app/service_overview/index.tsx index 0df6e9e1ebae0..98deba4f85a80 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/app/service_overview/index.tsx +++ b/x-pack/plugins/observability_solution/apm/public/components/app/service_overview/index.tsx @@ -97,7 +97,7 @@ export function ServiceOverview() { setDismissedLogsOnlyEmptyState(true)} + onDismiss={() => setDismissedLogsOnlyEmptyState(true)} /> )} diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/service_tab_empty_state/constants.ts b/x-pack/plugins/observability_solution/apm/public/components/app/service_tab_empty_state/constants.ts index 8551745238e43..312ed042bb8de 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/app/service_tab_empty_state/constants.ts +++ b/x-pack/plugins/observability_solution/apm/public/components/app/service_tab_empty_state/constants.ts @@ -5,9 +5,12 @@ * 2.0. */ +import type { ObservabilityOnboardingLocatorParams } from '@kbn/deeplinks-observability'; import { i18n } from '@kbn/i18n'; +import type { AddDataPanelProps } from '@kbn/observability-shared-plugin/public'; +import type { LocatorPublic } from '@kbn/share-plugin/common'; -export type EmptyStateKey = +export type AddAPMCalloutKeys = | 'serviceOverview' | 'serviceDependencies' | 'infraOverview' @@ -16,80 +19,154 @@ export type EmptyStateKey = | 'metrics' | 'errorGroupOverview'; -interface EmptyStateContent { - title: string; - content: string; - imgName?: string; -} +const defaultActions = ( + locator: LocatorPublic | undefined +) => { + return { + actions: { + primary: { + href: locator?.getRedirectUrl({ category: 'application' }), + label: i18n.translate('xpack.apm.serviceTabEmptyState.defaultPrimaryActionLabel', { + defaultMessage: 'Add APM', + }), + }, + secondary: { + href: 'https://ela.st/demo-apm-try-it', + }, + link: { + href: 'https://www.elastic.co/observability/application-performance-monitoring', + }, + }, + }; +}; -export const emptyStateDefinitions: Record = { - serviceOverview: { - title: i18n.translate('xpack.apm.serviceTabEmptyState.overviewTitle', { - defaultMessage: 'Detect and resolve issues faster with deep visibility into your application', - }), - content: i18n.translate('xpack.apm.serviceTabEmptyState.overviewContent', { - defaultMessage: - 'Understanding your application performance, relationships and dependencies by instrumenting with APM.', - }), - }, - serviceDependencies: { - title: i18n.translate('xpack.apm.serviceTabEmptyState.dependenciesTitle', { - defaultMessage: 'Understand the dependencies for your service', - }), - content: i18n.translate('xpack.apm.serviceTabEmptyState.dependenciesContent', { - defaultMessage: - "See your service's dependencies on both internal and third-party services by instrumenting with APM.", - }), - imgName: 'service_tab_empty_state_dependencies.png', - }, - infraOverview: { - title: i18n.translate('xpack.apm.serviceTabEmptyState.infrastructureTitle', { - defaultMessage: 'Understand what your service is running on', - }), - content: i18n.translate('xpack.apm.serviceTabEmptyState.infrastructureContent', { - defaultMessage: - 'Troubleshoot service problems by seeing the infrastructure your service is running on.', - }), - imgName: 'service_tab_empty_state_infrastructure.png', - }, - serviceMap: { - title: i18n.translate('xpack.apm.serviceTabEmptyState.serviceMapTitle', { - defaultMessage: 'Visualise the dependencies between your services', - }), - content: i18n.translate('xpack.apm.serviceTabEmptyState.serviceMapContent', { - defaultMessage: - 'See your services dependencies at a glance to help identify dependencies that may be affecting your service.', - }), - imgName: 'service_tab_empty_state_service_map.png', - }, - transactionOverview: { - title: i18n.translate('xpack.apm.serviceTabEmptyState.transactionsTitle', { - defaultMessage: 'Troubleshoot latency, throughput and errors', - }), - content: i18n.translate('xpack.apm.serviceTabEmptyState.transactionsContent', { - defaultMessage: - "Troubleshoot your service's performance by analysing latency, throughput and errors down to the specific transaction.", - }), - imgName: 'service_tab_empty_state_transactions.png', - }, - metrics: { - title: i18n.translate('xpack.apm.serviceTabEmptyState.metricsTitle', { - defaultMessage: 'View core metrics for your application', - }), - content: i18n.translate('xpack.apm.serviceTabEmptyState.metricsContent', { - defaultMessage: - 'View metric trends for the instances of your service to identify performance bottlenecks that could be affecting your users.', - }), - imgName: 'service_tab_empty_state_metrics.png', - }, - errorGroupOverview: { - title: i18n.translate('xpack.apm.serviceTabEmptyState.errorGroupOverviewTitle', { - defaultMessage: 'Identify transaction errors with your applications', - }), - content: i18n.translate('xpack.apm.serviceTabEmptyState.errorGroupOverviewContent', { - defaultMessage: - 'Analyse errors down to the specific transaction to pin-point specific errors within your service.', - }), - imgName: 'service_tab_empty_state_errors.png', - }, +export const addAPMCalloutDefinitions = ( + baseFolderPath: string, + locator: LocatorPublic | undefined +): Record< + AddAPMCalloutKeys, + Omit +> => { + return { + serviceOverview: { + content: { + title: i18n.translate('xpack.apm.serviceTabEmptyState.overviewTitle', { + defaultMessage: + 'Detect and resolve issues faster with deep visibility into your application', + }), + content: i18n.translate('xpack.apm.serviceTabEmptyState.overviewContent', { + defaultMessage: + 'Understanding your application performance, relationships and dependencies by instrumenting with APM.', + }), + img: { + name: 'service_tab_empty_state_overview.png', + baseFolderPath, + position: 'inside', + }, + }, + ...defaultActions(locator), + }, + serviceDependencies: { + content: { + title: i18n.translate('xpack.apm.serviceTabEmptyState.dependenciesTitle', { + defaultMessage: 'Understand the dependencies for your service', + }), + content: i18n.translate('xpack.apm.serviceTabEmptyState.dependenciesContent', { + defaultMessage: + "See your service's dependencies on both internal and third-party services by instrumenting with APM.", + }), + img: { + name: 'service_tab_empty_state_dependencies.png', + baseFolderPath, + position: 'below', + }, + }, + ...defaultActions(locator), + }, + infraOverview: { + content: { + title: i18n.translate('xpack.apm.serviceTabEmptyState.infrastructureTitle', { + defaultMessage: 'Understand what your service is running on', + }), + content: i18n.translate('xpack.apm.serviceTabEmptyState.infrastructureContent', { + defaultMessage: + 'Troubleshoot service problems by seeing the infrastructure your service is running on.', + }), + img: { + name: 'service_tab_empty_state_infrastructure.png', + baseFolderPath, + position: 'below', + }, + }, + ...defaultActions(locator), + }, + serviceMap: { + content: { + title: i18n.translate('xpack.apm.serviceTabEmptyState.serviceMapTitle', { + defaultMessage: 'Visualise the dependencies between your services', + }), + content: i18n.translate('xpack.apm.serviceTabEmptyState.serviceMapContent', { + defaultMessage: + 'See your services dependencies at a glance to help identify dependencies that may be affecting your service.', + }), + img: { + name: 'service_tab_empty_state_service_map.png', + baseFolderPath, + position: 'below', + }, + }, + ...defaultActions(locator), + }, + transactionOverview: { + content: { + title: i18n.translate('xpack.apm.serviceTabEmptyState.transactionsTitle', { + defaultMessage: 'Troubleshoot latency, throughput and errors', + }), + content: i18n.translate('xpack.apm.serviceTabEmptyState.transactionsContent', { + defaultMessage: + "Troubleshoot your service's performance by analysing latency, throughput and errors down to the specific transaction.", + }), + img: { + name: 'service_tab_empty_state_transactions.png', + baseFolderPath, + position: 'below', + }, + }, + ...defaultActions(locator), + }, + metrics: { + content: { + title: i18n.translate('xpack.apm.serviceTabEmptyState.metricsTitle', { + defaultMessage: 'View core metrics for your application', + }), + content: i18n.translate('xpack.apm.serviceTabEmptyState.metricsContent', { + defaultMessage: + 'View metric trends for the instances of your service to identify performance bottlenecks that could be affecting your users.', + }), + img: { + name: 'service_tab_empty_state_metrics.png', + baseFolderPath, + position: 'below', + }, + }, + ...defaultActions(locator), + }, + errorGroupOverview: { + content: { + title: i18n.translate('xpack.apm.serviceTabEmptyState.errorGroupOverviewTitle', { + defaultMessage: 'Identify transaction errors with your applications', + }), + content: i18n.translate('xpack.apm.serviceTabEmptyState.errorGroupOverviewContent', { + defaultMessage: + 'Analyse errors down to the specific transaction to pin-point specific errors within your service.', + }), + img: { + name: 'service_tab_empty_state_errors.png', + baseFolderPath, + position: 'below', + }, + }, + ...defaultActions(locator), + }, + }; }; diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/service_tab_empty_state/index.tsx b/x-pack/plugins/observability_solution/apm/public/components/app/service_tab_empty_state/index.tsx index a8962fcc1d2f7..f6493e213cce9 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/app/service_tab_empty_state/index.tsx +++ b/x-pack/plugins/observability_solution/apm/public/components/app/service_tab_empty_state/index.tsx @@ -5,50 +5,24 @@ * 2.0. */ -/* eslint-disable @elastic/eui/href-or-on-click */ - -import { - EuiButton, - EuiButtonIcon, - EuiFlexGroup, - EuiFlexItem, - EuiImage, - EuiLink, - EuiPanel, - EuiSpacer, - EuiText, - EuiTitle, - useEuiTheme, -} from '@elastic/eui'; import React from 'react'; -import { i18n } from '@kbn/i18n'; import { useKibana } from '@kbn/kibana-react-plugin/public'; +import { AddDataPanel } from '@kbn/observability-shared-plugin/public'; +import { + OBSERVABILITY_ONBOARDING_LOCATOR, + ObservabilityOnboardingLocatorParams, +} from '@kbn/deeplinks-observability'; +import { useApmPluginContext } from '../../../context/apm_plugin/use_apm_plugin_context'; import { EmptyStateClickParams, EntityInventoryAddDataParams } from '../../../services/telemetry'; import { ApmPluginStartDeps, ApmServices } from '../../../plugin'; -import { useApmPluginContext } from '../../../context/apm_plugin/use_apm_plugin_context'; import { useKibanaUrl } from '../../../hooks/use_kibana_url'; -import { AddApmData } from '../../shared/add_data_buttons/buttons'; -import { emptyStateDefinitions, EmptyStateKey } from './constants'; +import { addAPMCalloutDefinitions, AddAPMCalloutKeys } from './constants'; export interface ServiceTabEmptyStateProps { - id: EmptyStateKey; - onDissmiss?: () => void; + id: AddAPMCalloutKeys; + onDismiss?: () => void; } -const tryItNowButton = { - label: i18n.translate('xpack.apm.serviceTabEmptyState.tryItNowButtonLabel', { - defaultMessage: 'Try it now in our demo cluster', - }), - href: 'https://ela.st/demo-apm-try-it', -}; - -const learnMoreLink = { - label: i18n.translate('xpack.apm.serviceTabEmptyState.learnMoreLinkLabel', { - defaultMessage: 'Learn more', - }), - href: 'https://www.elastic.co/observability/application-performance-monitoring', -}; - const baseImgFolder = '/plugins/apm/assets/service_tab_empty_state'; const defaultAddDataTelemetryParams: EntityInventoryAddDataParams = { view: 'add_apm_cta', @@ -58,114 +32,40 @@ const defaultClickTelemetryParams: EmptyStateClickParams = { view: 'add_apm_cta', }; -export function ServiceTabEmptyState({ id, onDissmiss }: ServiceTabEmptyStateProps) { - const { euiTheme } = useEuiTheme(); - const { services } = useKibana(); - const { core } = useApmPluginContext(); +export function ServiceTabEmptyState({ id, onDismiss }: ServiceTabEmptyStateProps) { + const { + services: { telemetry }, + } = useKibana(); - const imgFolder = `${baseImgFolder}/${ - core.uiSettings.get('theme:darkMode') === 'enabled' ? 'dark' : 'light' - }`; - const imgName = emptyStateDefinitions[id].imgName; - const imgSrc = useKibanaUrl( - `${imgFolder}/${imgName ? imgName : 'service_tab_empty_state_overview.png'}` + const { share } = useApmPluginContext(); + + const onboardingLocator = share.url.locators.get( + OBSERVABILITY_ONBOARDING_LOCATOR ); + const imgBaseFolderPath = useKibanaUrl(baseImgFolder); + function handleAddAPMClick() { - services.telemetry.reportEntityInventoryAddData(defaultAddDataTelemetryParams); + telemetry.reportEntityInventoryAddData(defaultAddDataTelemetryParams); } function handleTryItClick() { - services.telemetry.reportTryItClick(defaultClickTelemetryParams); + telemetry.reportTryItClick(defaultClickTelemetryParams); } function handleLearnMoreClick() { - services.telemetry.reportLearnMoreClick(defaultClickTelemetryParams); + telemetry.reportLearnMoreClick(defaultClickTelemetryParams); } return ( - <> - - - - -

{emptyStateDefinitions[id].title}

-
- - {emptyStateDefinitions[id].content} - - - - - - - - {tryItNowButton.label} - - - - - {learnMoreLink.label} - - - -
- {!emptyStateDefinitions[id].imgName && ( - - - - )} - - {onDissmiss && ( - - )} -
-
- {emptyStateDefinitions[id].imgName && ( - <> - - - - )} - + ); } diff --git a/x-pack/plugins/observability_solution/apm/public/components/routing/templates/apm_main_template/entities_inventory_callout.tsx b/x-pack/plugins/observability_solution/apm/public/components/routing/templates/apm_main_template/entities_inventory_callout.tsx index 16cc93e2827f2..16eeba5e67ef4 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/routing/templates/apm_main_template/entities_inventory_callout.tsx +++ b/x-pack/plugins/observability_solution/apm/public/components/routing/templates/apm_main_template/entities_inventory_callout.tsx @@ -13,10 +13,10 @@ import { useKibana } from '@kbn/kibana-react-plugin/public'; import { ApmPluginStartDeps } from '../../../../plugin'; interface EntitiesInventoryCalloutProps { - onDissmiss: () => void; + onDismiss: () => void; } -export function EntitiesInventoryCallout({ onDissmiss }: EntitiesInventoryCalloutProps) { +export function EntitiesInventoryCallout({ onDismiss }: EntitiesInventoryCalloutProps) { const { services } = useKibana(); const { observabilityShared } = services; @@ -50,7 +50,7 @@ export function EntitiesInventoryCallout({ onDissmiss }: EntitiesInventoryCallou diff --git a/x-pack/plugins/observability_solution/apm/public/components/routing/templates/apm_main_template/index.tsx b/x-pack/plugins/observability_solution/apm/public/components/routing/templates/apm_main_template/index.tsx index 3f05d872f6d1f..b7fadf8c12870 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/routing/templates/apm_main_template/index.tsx +++ b/x-pack/plugins/observability_solution/apm/public/components/routing/templates/apm_main_template/index.tsx @@ -176,7 +176,7 @@ export function ApmMainTemplate({ {showEntitiesInventoryCallout ? ( { + onDismiss={() => { setdismissedEntitiesInventoryCallout(true); }} /> diff --git a/x-pack/plugins/observability_solution/infra/public/components/asset_details/add_metrics_callout/index.tsx b/x-pack/plugins/observability_solution/infra/public/components/asset_details/add_metrics_callout/index.tsx index c4132a1e29a3a..bd749baed7114 100644 --- a/x-pack/plugins/observability_solution/infra/public/components/asset_details/add_metrics_callout/index.tsx +++ b/x-pack/plugins/observability_solution/infra/public/components/asset_details/add_metrics_callout/index.tsx @@ -56,7 +56,7 @@ export function AddMetricsCallout({ id, onDismiss }: AddMetricsCalloutProps) { onAddData={handleAddMetricsClick} onTryIt={handleTryItClick} onLearnMore={handleLearnMoreClick} - onDissmiss={onDismiss && handleDismiss} + onDismiss={onDismiss && handleDismiss} /> ); } diff --git a/x-pack/plugins/observability_solution/observability_shared/public/components/add_data_panel/add_data_panel.stories.tsx b/x-pack/plugins/observability_solution/observability_shared/public/components/add_data_panel/add_data_panel.stories.tsx index 76442c0a4de0a..7915e4d010454 100644 --- a/x-pack/plugins/observability_solution/observability_shared/public/components/add_data_panel/add_data_panel.stories.tsx +++ b/x-pack/plugins/observability_solution/observability_shared/public/components/add_data_panel/add_data_panel.stories.tsx @@ -15,7 +15,7 @@ export default { }; const defaultFunctions = { - onDissmiss: () => alert('Dismissed'), + onDismiss: () => alert('Dismissed'), onAddData: () => alert('Add Data'), onTryIt: () => alert('Try It'), onLearnMore: () => alert('Learn More'), @@ -139,7 +139,7 @@ export function NotDismissable(props: ComponentProps) { NotDismissable.args = { ...defaultContent(), ...defaultFunctions, - onDissmiss: undefined, + onDismiss: undefined, actions: { primary: defaultPrimaryAction, secondary: { diff --git a/x-pack/plugins/observability_solution/observability_shared/public/components/add_data_panel/index.tsx b/x-pack/plugins/observability_solution/observability_shared/public/components/add_data_panel/index.tsx index ec6e405adcb26..f047fdb6b33d3 100644 --- a/x-pack/plugins/observability_solution/observability_shared/public/components/add_data_panel/index.tsx +++ b/x-pack/plugins/observability_solution/observability_shared/public/components/add_data_panel/index.tsx @@ -43,7 +43,7 @@ type AddDataPanelButtonWithLabel = Required; export interface AddDataPanelProps { content: AddDataPanelContent; - onDissmiss?: () => void; + onDismiss?: () => void; onAddData: () => void; onTryIt?: () => void; onLearnMore: () => void; @@ -72,7 +72,7 @@ const learnMoreDefaultLabel = i18n.translate( export function AddDataPanel({ content, actions, - onDissmiss, + onDismiss, onLearnMore, onTryIt, onAddData, @@ -155,7 +155,7 @@ export function AddDataPanel({ )} - {onDissmiss && ( + {onDismiss && ( )}