diff --git a/x-pack/plugins/observability_solution/apm/public/context/breadcrumbs/context.tsx b/x-pack/plugins/observability_solution/apm/public/context/breadcrumbs/context.tsx index e661ef2450310..7ec17b3a6cf3b 100644 --- a/x-pack/plugins/observability_solution/apm/public/context/breadcrumbs/context.tsx +++ b/x-pack/plugins/observability_solution/apm/public/context/breadcrumbs/context.tsx @@ -76,7 +76,7 @@ export function BreadcrumbsContextProvider({ children }: { children: React.React }; }); - useBreadcrumbs(formattedBreadcrumbs, { serverless }); + useBreadcrumbs(formattedBreadcrumbs, { serverless, absoluteProjectStyleBreadcrumbs: false }); return {children}; } diff --git a/x-pack/plugins/observability_solution/apm/public/context/breadcrumbs/use_breadcrumb.ts b/x-pack/plugins/observability_solution/apm/public/context/breadcrumbs/use_breadcrumb.ts index a6b80fd088bff..846aa1ec70877 100644 --- a/x-pack/plugins/observability_solution/apm/public/context/breadcrumbs/use_breadcrumb.ts +++ b/x-pack/plugins/observability_solution/apm/public/context/breadcrumbs/use_breadcrumb.ts @@ -8,8 +8,10 @@ import { useCurrentRoute } from '@kbn/typed-react-router-config'; import { useContext, useEffect, useRef } from 'react'; import { castArray } from 'lodash'; +import useObservable from 'react-use/lib/useObservable'; import { Breadcrumb, BreadcrumbsContext } from './context'; import { useKibanaEnvironmentContext } from '../kibana_environment_context/use_kibana_environment_context'; +import { useKibana } from '../kibana_context/use_kibana'; export function useBreadcrumb( callback: () => Breadcrumb | Breadcrumb[], @@ -17,6 +19,9 @@ export function useBreadcrumb( options?: { omitRootOnServerless?: boolean; omitOnServerless?: boolean } ) { const { isServerlessEnv } = useKibanaEnvironmentContext(); + const { + services: { chrome }, + } = useKibana(); const { omitRootOnServerless = false, omitOnServerless = false } = options || {}; const api = useContext(BreadcrumbsContext); @@ -29,8 +34,11 @@ export function useBreadcrumb( const matchedRoute = useRef(match?.route); + const chromeStyle = useObservable(chrome.getChromeStyle$()); + useEffect(() => { - if (isServerlessEnv && omitOnServerless) { + const isProjectStyle = isServerlessEnv || chromeStyle === 'project'; + if (isProjectStyle && omitOnServerless) { return; } @@ -42,10 +50,9 @@ export function useBreadcrumb( if (matchedRoute.current) { const breadcrumbs = castArray(callback()); - api.set( matchedRoute.current, - isServerlessEnv && omitRootOnServerless && breadcrumbs.length >= 1 + isProjectStyle && omitRootOnServerless && breadcrumbs.length >= 1 ? breadcrumbs.slice(1) : breadcrumbs ); @@ -57,5 +64,5 @@ export function useBreadcrumb( } }; // eslint-disable-next-line react-hooks/exhaustive-deps - }, [match, ...fnDeps]); + }, [match, chromeStyle, ...fnDeps]); } diff --git a/x-pack/plugins/observability_solution/exploratory_view/public/components/shared/exploratory_view/index.tsx b/x-pack/plugins/observability_solution/exploratory_view/public/components/shared/exploratory_view/index.tsx index c4061f05ce91b..750429602aecf 100644 --- a/x-pack/plugins/observability_solution/exploratory_view/public/components/shared/exploratory_view/index.tsx +++ b/x-pack/plugins/observability_solution/exploratory_view/public/components/shared/exploratory_view/index.tsx @@ -60,7 +60,7 @@ export function ExploratoryViewPage({ }), }, ], - { app } + { app, classicOnly: true } ); const kbnUrlStateStorage = useSessionStorage diff --git a/x-pack/plugins/observability_solution/infra/public/components/asset_details/template/page.tsx b/x-pack/plugins/observability_solution/infra/public/components/asset_details/template/page.tsx index c6e8790eeff6a..5c187bb6186d6 100644 --- a/x-pack/plugins/observability_solution/infra/public/components/asset_details/template/page.tsx +++ b/x-pack/plugins/observability_solution/infra/public/components/asset_details/template/page.tsx @@ -50,18 +50,15 @@ export const Page = ({ tabs = [], links = [] }: ContentTemplateProps) => { const parentBreadcrumbResolver = useParentBreadcrumbResolver(); const breadcrumbOptions = parentBreadcrumbResolver.getBreadcrumbOptions(asset.type); - useMetricsBreadcrumbs( - [ - { - ...breadcrumbOptions.link, - text: breadcrumbOptions.text, - }, - { - text: asset.name, - }, - ], - { deeperContextServerless: true } - ); + useMetricsBreadcrumbs([ + { + ...breadcrumbOptions.link, + text: breadcrumbOptions.text, + }, + { + text: asset.name, + }, + ]); useEffect(() => { if (trackOnlyOnce.current) { diff --git a/x-pack/plugins/observability_solution/infra/public/hooks/use_breadcrumbs.ts b/x-pack/plugins/observability_solution/infra/public/hooks/use_breadcrumbs.ts deleted file mode 100644 index 0cf9efef908bb..0000000000000 --- a/x-pack/plugins/observability_solution/infra/public/hooks/use_breadcrumbs.ts +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { ChromeBreadcrumb } from '@kbn/core/public'; -import { useEffect } from 'react'; -import { useLinkProps } from '@kbn/observability-shared-plugin/public'; -import { observabilityTitle } from '../translations'; -import { useKibanaContextForPlugin } from './use_kibana'; - -type AppId = 'logs' | 'metrics'; - -export const useBreadcrumbs = (app: AppId, appTitle: string, extraCrumbs: ChromeBreadcrumb[]) => { - const { - services: { chrome }, - } = useKibanaContextForPlugin(); - - const observabilityLinkProps = useLinkProps({ app: 'observability-overview' }); - const appLinkProps = useLinkProps({ app }); - - useEffect(() => { - const breadcrumbs = [ - { - ...observabilityLinkProps, - text: observabilityTitle, - }, - { - ...appLinkProps, - text: appTitle, - }, - ...extraCrumbs, - ]; - - const docTitle = [...breadcrumbs].reverse().map((breadcrumb) => breadcrumb.text as string); - - chrome.docTitle.change(docTitle); - chrome.setBreadcrumbs(breadcrumbs); - }, [appLinkProps, appTitle, chrome, extraCrumbs, observabilityLinkProps]); -}; diff --git a/x-pack/plugins/observability_solution/infra/public/hooks/use_logs_breadcrumbs.tsx b/x-pack/plugins/observability_solution/infra/public/hooks/use_logs_breadcrumbs.tsx index d2fc556caa57b..2eba7845b8d24 100644 --- a/x-pack/plugins/observability_solution/infra/public/hooks/use_logs_breadcrumbs.tsx +++ b/x-pack/plugins/observability_solution/infra/public/hooks/use_logs_breadcrumbs.tsx @@ -6,10 +6,18 @@ */ import { ChromeBreadcrumb } from '@kbn/core/public'; -import { useBreadcrumbs } from './use_breadcrumbs'; +import { useBreadcrumbs, useLinkProps } from '@kbn/observability-shared-plugin/public'; import { LOGS_APP } from '../../common/constants'; import { logsTitle } from '../translations'; export const useLogsBreadcrumbs = (extraCrumbs: ChromeBreadcrumb[]) => { - useBreadcrumbs(LOGS_APP, logsTitle, extraCrumbs); + const appLinkProps = useLinkProps({ app: LOGS_APP }); + const breadcrumbs = [ + { + ...appLinkProps, + text: logsTitle, + }, + ...extraCrumbs, + ]; + useBreadcrumbs(breadcrumbs, { classicOnly: true }); }; diff --git a/x-pack/plugins/observability_solution/infra/public/hooks/use_metrics_breadcrumbs.tsx b/x-pack/plugins/observability_solution/infra/public/hooks/use_metrics_breadcrumbs.tsx index defc8b3210f48..d5a6011a68e8e 100644 --- a/x-pack/plugins/observability_solution/infra/public/hooks/use_metrics_breadcrumbs.tsx +++ b/x-pack/plugins/observability_solution/infra/public/hooks/use_metrics_breadcrumbs.tsx @@ -5,42 +5,25 @@ * 2.0. */ -import { useEffect, useMemo } from 'react'; import { ChromeBreadcrumb } from '@kbn/core/public'; import { useBreadcrumbs, useLinkProps } from '@kbn/observability-shared-plugin/public'; import { METRICS_APP } from '../../common/constants'; import { metricsTitle } from '../translations'; import { useKibanaContextForPlugin } from './use_kibana'; -export const useMetricsBreadcrumbs = ( - extraCrumbs: ChromeBreadcrumb[], - options?: { deeperContextServerless: boolean } -) => { +export const useMetricsBreadcrumbs = (extraCrumbs: ChromeBreadcrumb[]) => { const { services: { serverless }, } = useKibanaContextForPlugin(); const appLinkProps = useLinkProps({ app: METRICS_APP }); - const breadcrumbs = useMemo( - () => [ - { - ...appLinkProps, - text: metricsTitle, - }, - ...extraCrumbs, - ], - [appLinkProps, extraCrumbs] - ); + const breadcrumbs = [ + { + ...appLinkProps, + text: metricsTitle, + }, + ...extraCrumbs, + ]; - useBreadcrumbs(breadcrumbs); - - useEffect(() => { - // For deeper context breadcrumbs in serveless, the `serverless` plugin provides its own breadcrumb service. - // https://docs.elastic.dev/kibana-dev-docs/serverless-project-navigation#breadcrumbs - if (serverless && options?.deeperContextServerless) { - // The initial path is already set in the breadcrumbs - const [, ...serverlessBreadcrumbs] = breadcrumbs; - serverless.setBreadcrumbs(serverlessBreadcrumbs); - } - }, [breadcrumbs, options?.deeperContextServerless, serverless]); + useBreadcrumbs(breadcrumbs, { serverless }); }; diff --git a/x-pack/plugins/observability_solution/infra/public/pages/metrics/metric_detail/metric_detail_page.tsx b/x-pack/plugins/observability_solution/infra/public/pages/metrics/metric_detail/metric_detail_page.tsx index 65ab15a5713be..0e6183268ddda 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/metrics/metric_detail/metric_detail_page.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/metrics/metric_detail/metric_detail_page.tsx @@ -54,18 +54,15 @@ export const MetricDetailPage = () => { }); const breadcrumbOptions = parentBreadcrumbResolver.getBreadcrumbOptions(nodeType); - useMetricsBreadcrumbs( - [ - { - ...breadcrumbOptions.link, - text: breadcrumbOptions.text, - }, - { - text: name, - }, - ], - { deeperContextServerless: true } - ); + useMetricsBreadcrumbs([ + { + ...breadcrumbOptions.link, + text: breadcrumbOptions.text, + }, + { + text: name, + }, + ]); const [sideNav, setSideNav] = useState([]); diff --git a/x-pack/plugins/observability_solution/infra/public/translations.ts b/x-pack/plugins/observability_solution/infra/public/translations.ts index ecb72b3df4b01..3377ae1dd1fa1 100644 --- a/x-pack/plugins/observability_solution/infra/public/translations.ts +++ b/x-pack/plugins/observability_solution/infra/public/translations.ts @@ -39,7 +39,7 @@ export const metricsTitle = i18n.translate('xpack.infra.header.infrastructureTit }); export const inventoryTitle = i18n.translate('xpack.infra.metrics.infrastructureInventoryTitle', { - defaultMessage: 'Infrastructure Inventory', + defaultMessage: 'Infrastructure inventory', }); export const metricsExplorerTitle = i18n.translate('xpack.infra.metrics.metricsExplorerTitle', { diff --git a/x-pack/plugins/observability_solution/observability/public/pages/alert_details/alert_details.tsx b/x-pack/plugins/observability_solution/observability/public/pages/alert_details/alert_details.tsx index 8f5acee54f57e..9403090b1e213 100644 --- a/x-pack/plugins/observability_solution/observability/public/pages/alert_details/alert_details.tsx +++ b/x-pack/plugins/observability_solution/observability/public/pages/alert_details/alert_details.tsx @@ -93,6 +93,7 @@ export function AlertDetails() { triggersActionsUi: { ruleTypeRegistry }, observabilityAIAssistant, uiSettings, + serverless, } = useKibana().services; const { search } = useLocation(); @@ -158,20 +159,23 @@ export function AlertDetails() { } }, [alertDetail, ruleTypeRegistry]); - useBreadcrumbs([ - { - href: http.basePath.prepend(paths.observability.alerts), - text: i18n.translate('xpack.observability.breadcrumbs.alertsLinkText', { - defaultMessage: 'Alerts', - }), - deepLinkId: 'observability-overview:alerts', - }, - { - text: alertDetail - ? getPageTitle(alertDetail.formatted.fields[ALERT_RULE_CATEGORY]) - : defaultBreadcrumb, - }, - ]); + useBreadcrumbs( + [ + { + href: http.basePath.prepend(paths.observability.alerts), + text: i18n.translate('xpack.observability.breadcrumbs.alertsLinkText', { + defaultMessage: 'Alerts', + }), + deepLinkId: 'observability-overview:alerts', + }, + { + text: alertDetail + ? getPageTitle(alertDetail.formatted.fields[ALERT_RULE_CATEGORY]) + : defaultBreadcrumb, + }, + ], + { serverless } + ); const onUntrackAlert = () => { setAlertStatus(ALERT_STATUS_UNTRACKED); diff --git a/x-pack/plugins/observability_solution/observability/public/pages/alerts/alerts.tsx b/x-pack/plugins/observability_solution/observability/public/pages/alerts/alerts.tsx index ef883f40f4902..6607052225555 100644 --- a/x-pack/plugins/observability_solution/observability/public/pages/alerts/alerts.tsx +++ b/x-pack/plugins/observability_solution/observability/public/pages/alerts/alerts.tsx @@ -159,13 +159,18 @@ function InternalAlertsPage() { [alertSearchBarStateProps.rangeFrom, alertSearchBarStateProps.rangeTo, bucketSize, esQuery] ); - useBreadcrumbs([ + useBreadcrumbs( + [ + { + text: i18n.translate('xpack.observability.breadcrumbs.alertsLinkText', { + defaultMessage: 'Alerts', + }), + }, + ], { - text: i18n.translate('xpack.observability.breadcrumbs.alertsLinkText', { - defaultMessage: 'Alerts', - }), - }, - ]); + classicOnly: true, + } + ); async function loadRuleStats() { setRuleStatsLoading(true); diff --git a/x-pack/plugins/observability_solution/observability/public/pages/overview/overview.tsx b/x-pack/plugins/observability_solution/observability/public/pages/overview/overview.tsx index 37942cdbca7d6..c7b71431050cf 100644 --- a/x-pack/plugins/observability_solution/observability/public/pages/overview/overview.tsx +++ b/x-pack/plugins/observability_solution/observability/public/pages/overview/overview.tsx @@ -56,13 +56,18 @@ export function OverviewPage() { const { ObservabilityPageTemplate, observabilityRuleTypeRegistry } = usePluginContext(); - useBreadcrumbs([ + useBreadcrumbs( + [ + { + text: i18n.translate('xpack.observability.breadcrumbs.overviewLinkText', { + defaultMessage: 'Overview', + }), + }, + ], { - text: i18n.translate('xpack.observability.breadcrumbs.overviewLinkText', { - defaultMessage: 'Overview', - }), - }, - ]); + classicOnly: true, + } + ); const { data: newsFeed } = useFetcher( () => getNewsFeed({ http, kibanaVersion }), diff --git a/x-pack/plugins/observability_solution/observability/public/pages/rule_details/rule_details.tsx b/x-pack/plugins/observability_solution/observability/public/pages/rule_details/rule_details.tsx index e8270434c12b2..3b2e5d3118c4a 100644 --- a/x-pack/plugins/observability_solution/observability/public/pages/rule_details/rule_details.tsx +++ b/x-pack/plugins/observability_solution/observability/public/pages/rule_details/rule_details.tsx @@ -61,6 +61,7 @@ export function RuleDetailsPage() { getRuleDefinition: RuleDefinition, getRuleStatusPanel: RuleStatusPanel, }, + serverless, } = useKibana().services; const { ObservabilityPageTemplate } = usePluginContext(); @@ -72,24 +73,27 @@ export function RuleDetailsPage() { filterByRuleTypeIds: filteredRuleTypes, }); - useBreadcrumbs([ - { - text: i18n.translate('xpack.observability.breadcrumbs.alertsLinkText', { - defaultMessage: 'Alerts', - }), - href: basePath.prepend(paths.observability.alerts), - deepLinkId: 'observability-overview:alerts', - }, - { - href: basePath.prepend(paths.observability.rules), - text: i18n.translate('xpack.observability.breadcrumbs.rulesLinkText', { - defaultMessage: 'Rules', - }), - }, - { - text: rule && rule.name, - }, - ]); + useBreadcrumbs( + [ + { + text: i18n.translate('xpack.observability.breadcrumbs.alertsLinkText', { + defaultMessage: 'Alerts', + }), + href: basePath.prepend(paths.observability.alerts), + deepLinkId: 'observability-overview:alerts', + }, + { + href: basePath.prepend(paths.observability.rules), + text: i18n.translate('xpack.observability.breadcrumbs.rulesLinkText', { + defaultMessage: 'Rules', + }), + }, + { + text: rule && rule.name, + }, + ], + { serverless } + ); const [activeTabId, setActiveTabId] = useState(() => { const searchParams = new URLSearchParams(search); diff --git a/x-pack/plugins/observability_solution/observability/public/pages/rules/rules.tsx b/x-pack/plugins/observability_solution/observability/public/pages/rules/rules.tsx index fb257f9f95cde..b94b9a7e4218f 100644 --- a/x-pack/plugins/observability_solution/observability/public/pages/rules/rules.tsx +++ b/x-pack/plugins/observability_solution/observability/public/pages/rules/rules.tsx @@ -42,6 +42,7 @@ export function RulesPage({ activeTab = RULES_TAB_NAME }: RulesPageProps) { getAddRuleFlyout: AddRuleFlyout, getRulesSettingsLink: RulesSettingsLink, }, + serverless, } = useKibana().services; const { ObservabilityPageTemplate } = usePluginContext(); const history = useHistory(); @@ -50,20 +51,23 @@ export function RulesPage({ activeTab = RULES_TAB_NAME }: RulesPageProps) { const [addRuleFlyoutVisibility, setAddRuleFlyoutVisibility] = useState(false); const [stateRefresh, setRefresh] = useState(new Date()); - useBreadcrumbs([ - { - text: i18n.translate('xpack.observability.breadcrumbs.alertsLinkText', { - defaultMessage: 'Alerts', - }), - href: http.basePath.prepend('/app/observability/alerts'), - deepLinkId: 'observability-overview:alerts', - }, - { - text: i18n.translate('xpack.observability.breadcrumbs.rulesLinkText', { - defaultMessage: 'Rules', - }), - }, - ]); + useBreadcrumbs( + [ + { + text: i18n.translate('xpack.observability.breadcrumbs.alertsLinkText', { + defaultMessage: 'Alerts', + }), + href: http.basePath.prepend('/app/observability/alerts'), + deepLinkId: 'observability-overview:alerts', + }, + { + text: i18n.translate('xpack.observability.breadcrumbs.rulesLinkText', { + defaultMessage: 'Rules', + }), + }, + ], + { serverless } + ); const filteredRuleTypes = useGetFilteredRuleTypes(); const { diff --git a/x-pack/plugins/observability_solution/observability_logs_explorer/public/routes/main/main_route.tsx b/x-pack/plugins/observability_solution/observability_logs_explorer/public/routes/main/main_route.tsx index d1a2dc1e74439..49b25c29dad53 100644 --- a/x-pack/plugins/observability_solution/observability_logs_explorer/public/routes/main/main_route.tsx +++ b/x-pack/plugins/observability_solution/observability_logs_explorer/public/routes/main/main_route.tsx @@ -21,26 +21,17 @@ import { } from '../../state_machines/observability_logs_explorer/src'; import { LazyOriginInterpreter } from '../../state_machines/origin_interpreter/src/lazy_component'; import { ObservabilityLogsExplorerHistory } from '../../types'; -import { noBreadcrumbs, useBreadcrumbs } from '../../utils/breadcrumbs'; +import { useBreadcrumbs } from '../../utils/breadcrumbs'; import { useKbnUrlStateStorageFromRouterContext } from '../../utils/kbn_url_state_context'; import { useKibanaContextForPlugin } from '../../utils/use_kibana'; export const ObservabilityLogsExplorerMainRoute = () => { const { services } = useKibanaContextForPlugin(); - const { - logsExplorer, - serverless, - chrome, - notifications, - appParams, - analytics, - i18n, - theme, - logsDataAccess, - } = services; + const { logsExplorer, notifications, appParams, analytics, i18n, theme, logsDataAccess } = + services; const { history } = appParams; - useBreadcrumbs(noBreadcrumbs, chrome, serverless); + useBreadcrumbs(); const urlStateStorageContainer = useKbnUrlStateStorageFromRouterContext(); diff --git a/x-pack/plugins/observability_solution/observability_logs_explorer/public/utils/breadcrumbs.tsx b/x-pack/plugins/observability_solution/observability_logs_explorer/public/utils/breadcrumbs.tsx index 5e84404239866..4c63476e9507d 100644 --- a/x-pack/plugins/observability_solution/observability_logs_explorer/public/utils/breadcrumbs.tsx +++ b/x-pack/plugins/observability_solution/observability_logs_explorer/public/utils/breadcrumbs.tsx @@ -5,71 +5,27 @@ * 2.0. */ -import { EuiBreadcrumb } from '@elastic/eui'; -import type { ChromeStart } from '@kbn/core-chrome-browser'; -import { - LOGS_APP_ID, - OBSERVABILITY_LOGS_EXPLORER_APP_ID, - OBSERVABILITY_OVERVIEW_APP_ID, -} from '@kbn/deeplinks-observability'; +import { LOGS_APP_ID, OBSERVABILITY_LOGS_EXPLORER_APP_ID } from '@kbn/deeplinks-observability'; import { useLinkProps } from '@kbn/observability-shared-plugin/public'; -import type { ServerlessPluginStart } from '@kbn/serverless/public'; -import { useEffect } from 'react'; -import { - logsExplorerAppTitle, - logsAppTitle, - observabilityAppTitle, -} from '../../common/translations'; +import { useMemo } from 'react'; +import { useBreadcrumbs as observabilityUseBreadcrumbs } from '@kbn/observability-shared-plugin/public'; +import { logsExplorerAppTitle, logsAppTitle } from '../../common/translations'; -export const useBreadcrumbs = ( - breadcrumbs: EuiBreadcrumb[], - chromeService: ChromeStart, - serverlessService?: ServerlessPluginStart -) => { - const observabilityLinkProps = useLinkProps({ app: OBSERVABILITY_OVERVIEW_APP_ID }); +export const useBreadcrumbs = () => { const logsLinkProps = useLinkProps({ app: LOGS_APP_ID }); const logsExplorerLinkProps = useLinkProps({ app: OBSERVABILITY_LOGS_EXPLORER_APP_ID }); + const classicCrumbs = useMemo(() => { + return [ + { + text: logsAppTitle, + ...logsLinkProps, + }, + { + text: logsExplorerAppTitle, + ...logsExplorerLinkProps, + }, + ]; + }, [logsExplorerLinkProps, logsLinkProps]); - useEffect(() => { - setBreadcrumbs( - serverlessService - ? breadcrumbs - : [ - { - text: observabilityAppTitle, - ...observabilityLinkProps, - }, - { - text: logsAppTitle, - ...logsLinkProps, - }, - { - text: logsExplorerAppTitle, - ...logsExplorerLinkProps, - }, - ...breadcrumbs, - ], - chromeService, - serverlessService - ); - }, [breadcrumbs, chromeService, serverlessService]); // eslint-disable-line react-hooks/exhaustive-deps + observabilityUseBreadcrumbs(classicCrumbs, { classicOnly: true }); }; - -export function setBreadcrumbs( - breadcrumbs: EuiBreadcrumb[], - chromeService: ChromeStart, - serverlessService?: ServerlessPluginStart -) { - chromeService.docTitle.change(getDocTitle(breadcrumbs)); - if (serverlessService) { - serverlessService.setBreadcrumbs(breadcrumbs); - } else if (chromeService) { - chromeService.setBreadcrumbs(breadcrumbs); - } -} - -export function getDocTitle(breadcrumbs: EuiBreadcrumb[]) { - return breadcrumbs.map(({ text }) => text as string).reverse(); -} - -export const noBreadcrumbs: EuiBreadcrumb[] = []; diff --git a/x-pack/plugins/observability_solution/observability_logs_explorer/tsconfig.json b/x-pack/plugins/observability_solution/observability_logs_explorer/tsconfig.json index be2b3c9efdff6..5a2f18aa4249a 100644 --- a/x-pack/plugins/observability_solution/observability_logs_explorer/tsconfig.json +++ b/x-pack/plugins/observability_solution/observability_logs_explorer/tsconfig.json @@ -13,7 +13,6 @@ "kbn_references": [ "@kbn/config-schema", "@kbn/core", - "@kbn/core-chrome-browser", "@kbn/core-mount-utils-browser-internal", "@kbn/core-notifications-browser", "@kbn/data-plugin", diff --git a/x-pack/plugins/observability_solution/observability_shared/public/hooks/use_breadcrumbs.test.tsx b/x-pack/plugins/observability_solution/observability_shared/public/hooks/use_breadcrumbs.test.tsx index 15849039bde8b..c166057df0304 100644 --- a/x-pack/plugins/observability_solution/observability_shared/public/hooks/use_breadcrumbs.test.tsx +++ b/x-pack/plugins/observability_solution/observability_shared/public/hooks/use_breadcrumbs.test.tsx @@ -11,12 +11,18 @@ import { MemoryRouter } from 'react-router-dom'; import { CoreStart } from '@kbn/core/public'; import { createKibanaReactContext } from '@kbn/kibana-react-plugin/public'; import { useBreadcrumbs } from './use_breadcrumbs'; +import { BehaviorSubject } from 'rxjs'; +import { ChromeStyle } from '@kbn/core-chrome-browser'; const setBreadcrumbs = jest.fn(); const setTitle = jest.fn(); const kibanaServices = { application: { getUrlForApp: () => {}, navigateToApp: () => {} }, - chrome: { setBreadcrumbs, docTitle: { change: setTitle } }, + chrome: { + setBreadcrumbs, + docTitle: { change: setTitle }, + getChromeStyle$: () => new BehaviorSubject('classic').asObservable(), + }, uiSettings: { get: () => true }, settings: { client: { get: () => true } }, } as unknown as Partial; @@ -61,9 +67,15 @@ describe('useBreadcrumbs', () => { it('sets the overview breadcrumb', () => { renderHook(() => useBreadcrumbs([]), { wrapper: Wrapper }); - expect(setBreadcrumbs).toHaveBeenCalledWith([ - { href: '/overview', onClick: expect.any(Function), text: 'Observability' }, - ]); + expect(setBreadcrumbs).toHaveBeenCalledWith( + [{ href: '/overview', onClick: expect.any(Function), text: 'Observability' }], + { + project: { + absolute: true, + value: [{ href: '/overview', onClick: expect.any(Function), text: 'Observability' }], + }, + } + ); }); it('sets the overview title', () => { @@ -86,17 +98,29 @@ describe('useBreadcrumbs', () => { { wrapper: Wrapper } ); - expect(setBreadcrumbs).toHaveBeenCalledWith([ - { href: '/overview', onClick: expect.any(Function), text: 'Observability' }, + expect(setBreadcrumbs).toHaveBeenCalledWith( + [ + { href: '/overview', onClick: expect.any(Function), text: 'Observability' }, + { + href: '/one', + onClick: expect.any(Function), + text: 'One', + }, + { + text: 'Two', + }, + ], { - href: '/one', - onClick: expect.any(Function), - text: 'One', - }, - { - text: 'Two', - }, - ]); + project: { + absolute: true, + value: [ + { href: '/overview', onClick: expect.any(Function), text: 'Observability' }, + { href: '/one', onClick: expect.any(Function), text: 'One' }, + { text: 'Two' }, + ], + }, + } + ); }); it('sets the title', () => { diff --git a/x-pack/plugins/observability_solution/observability_shared/public/hooks/use_breadcrumbs.ts b/x-pack/plugins/observability_solution/observability_shared/public/hooks/use_breadcrumbs.ts index 4137d541c4e39..5c9c0d3981bb0 100644 --- a/x-pack/plugins/observability_solution/observability_shared/public/hooks/use_breadcrumbs.ts +++ b/x-pack/plugins/observability_solution/observability_shared/public/hooks/use_breadcrumbs.ts @@ -11,8 +11,16 @@ import { MouseEvent, useEffect, useMemo } from 'react'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import { ChromeBreadcrumbsAppendExtension } from '@kbn/core-chrome-browser'; import type { ServerlessPluginStart } from '@kbn/serverless/public'; +import useObservable from 'react-use/lib/useObservable'; import { useQueryParams } from './use_query_params'; +const OBSERVABILITY_TEXT = i18n.translate( + 'xpack.observabilityShared.breadcrumbs.observabilityLinkText', + { + defaultMessage: 'Observability', + } +); + function addClickHandlers( breadcrumbs: ChromeBreadcrumb[], navigateToHref?: (url: string) => Promise @@ -33,23 +41,49 @@ function addClickHandlers( } function getTitleFromBreadCrumbs(breadcrumbs: ChromeBreadcrumb[]) { - return breadcrumbs.map(({ text }) => text?.toString() ?? '').reverse(); + return breadcrumbs + .map(({ text }) => text?.toString() ?? '') + .reverse() + .concat([OBSERVABILITY_TEXT]); } +/** + * + * By default the breadcrumbs will be passed to either serverless.setBreadcrumbs or chrome.setBreadcrumbs depending on the + * environment. The breadcrumbs will *also* be passed to the project style breadcrumbs for stateful project style. We will use "project style" + * here to refer to serverless chrome and stateful project style chrome. Classic refers to stateful classic chrome. + * + * Project style breadcrumbs add a root crumb ("deployment" etc) and "nav crumbs" which are derived from the navigation structure. By default + * the "absolute" mode is used which means the breadcrumbs passed here will omit the navigation derived "nav crumbs". You can pass + * absoluteProjectStyleBreadcrumbs: false to include the 'smart' "nav crumbs". + * + * In classic mode (not project style) the 'Observability' crumb is added. + * + * You can also pass classicOnly to only set breadrumbs in the classic chrome context. This can be useful if your solution just wants to defer all project style crumbs to the "nav crumbs". + */ export const useBreadcrumbs = ( extraCrumbs: ChromeBreadcrumb[], options?: { app?: { id: string; label: string }; breadcrumbsAppendExtension?: ChromeBreadcrumbsAppendExtension; serverless?: ServerlessPluginStart; + absoluteProjectStyleBreadcrumbs?: boolean; + classicOnly?: boolean; } ) => { const params = useQueryParams(); const { app, breadcrumbsAppendExtension, serverless } = options ?? {}; + const absolute = options?.absoluteProjectStyleBreadcrumbs === false ? false : true; + const classicOnly = options?.classicOnly ?? false; const { services: { - chrome: { docTitle, setBreadcrumbs: chromeSetBreadcrumbs, setBreadcrumbsAppendExtension }, + chrome: { + docTitle, + setBreadcrumbs: chromeSetBreadcrumbs, + setBreadcrumbsAppendExtension, + getChromeStyle$, + }, application: { getUrlForApp, navigateToUrl }, }, } = useKibana<{ @@ -58,11 +92,27 @@ export const useBreadcrumbs = ( }>(); const setTitle = docTitle.change; const appPath = getUrlForApp(app?.id ?? 'observability-overview') ?? ''; + const chromeStyle = useObservable(getChromeStyle$()); - const setBreadcrumbs = useMemo( - () => serverless?.setBreadcrumbs ?? chromeSetBreadcrumbs, - [serverless, chromeSetBreadcrumbs] - ); + const setBreadcrumbs = useMemo(() => { + if (!serverless?.setBreadcrumbs) { + return (breadcrumbs: ChromeBreadcrumb[]) => + chromeSetBreadcrumbs( + breadcrumbs, + !classicOnly + ? { + project: { + value: breadcrumbs, + absolute, + }, + } + : undefined + ); + } + if (!classicOnly) + return (breadcrumbs: ChromeBreadcrumb[]) => + serverless?.setBreadcrumbs(breadcrumbs, { absolute }); + }, [serverless, classicOnly, absolute, chromeSetBreadcrumbs]); useEffect(() => { if (breadcrumbsAppendExtension) { @@ -76,15 +126,12 @@ export const useBreadcrumbs = ( }, [breadcrumbsAppendExtension, setBreadcrumbsAppendExtension]); useEffect(() => { - const breadcrumbs = serverless + const isProjectStyle = serverless || chromeStyle === 'project'; + const breadcrumbs = isProjectStyle ? extraCrumbs : [ { - text: - app?.label ?? - i18n.translate('xpack.observabilityShared.breadcrumbs.observabilityLinkText', { - defaultMessage: 'Observability', - }), + text: app?.label ?? OBSERVABILITY_TEXT, href: appPath + '/overview', }, ...extraCrumbs, @@ -94,11 +141,12 @@ export const useBreadcrumbs = ( setBreadcrumbs(addClickHandlers(breadcrumbs, navigateToUrl)); } if (setTitle) { - setTitle(getTitleFromBreadCrumbs(breadcrumbs)); + setTitle(getTitleFromBreadCrumbs(extraCrumbs)); } }, [ app?.label, appPath, + chromeStyle, extraCrumbs, navigateToUrl, params, diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slo_details/slo_details.tsx b/x-pack/plugins/observability_solution/slo/public/pages/slo_details/slo_details.tsx index 26cdf62b4f7b4..9a32c150e1b8c 100644 --- a/x-pack/plugins/observability_solution/slo/public/pages/slo_details/slo_details.tsx +++ b/x-pack/plugins/observability_solution/slo/public/pages/slo_details/slo_details.tsx @@ -40,6 +40,7 @@ export function SloDetailsPage() { application: { navigateToUrl }, http: { basePath }, observabilityAIAssistant, + serverless, } = useKibana().services; const { ObservabilityPageTemplate } = usePluginContext(); const { hasAtLeast } = useLicense(); @@ -105,7 +106,7 @@ export function SloDetailsPage() { } }, [onPageReady, slo, isLoading]); - useBreadcrumbs(getBreadcrumbs(basePath, slo)); + useBreadcrumbs(getBreadcrumbs(basePath, slo), { serverless }); const isSloNotFound = !isLoading && slo === undefined; if (isSloNotFound) { diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/slo_edit.tsx b/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/slo_edit.tsx index aa008838a8b3c..7dcce93c0d003 100644 --- a/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/slo_edit.tsx +++ b/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/slo_edit.tsx @@ -22,6 +22,7 @@ export function SloEditPage() { const { application: { navigateToUrl }, http: { basePath }, + serverless, } = useKibana().services; const { sloId } = useParams<{ sloId: string | undefined }>(); @@ -32,32 +33,35 @@ export function SloEditPage() { const hasRightLicense = hasAtLeast('platinum'); const { data: slo } = useFetchSloDetails({ sloId }); - useBreadcrumbs([ - { - href: basePath.prepend(paths.slos), - text: i18n.translate('xpack.slo.breadcrumbs.sloLabel', { - defaultMessage: 'SLOs', - }), - deepLinkId: 'slo', - }, - ...(!!slo - ? [ - { - href: basePath.prepend(paths.sloDetails(slo!.id)), - text: slo!.name, - }, - ] - : []), - { - text: slo - ? i18n.translate('xpack.slo.breadcrumbs.sloEditLabel', { - defaultMessage: 'Edit', - }) - : i18n.translate('xpack.slo.breadcrumbs.sloCreateLabel', { - defaultMessage: 'Create', - }), - }, - ]); + useBreadcrumbs( + [ + { + href: basePath.prepend(paths.slos), + text: i18n.translate('xpack.slo.breadcrumbs.sloLabel', { + defaultMessage: 'SLOs', + }), + deepLinkId: 'slo', + }, + ...(!!slo + ? [ + { + href: basePath.prepend(paths.sloDetails(slo!.id)), + text: slo!.name, + }, + ] + : []), + { + text: slo + ? i18n.translate('xpack.slo.breadcrumbs.sloEditLabel', { + defaultMessage: 'Edit', + }) + : i18n.translate('xpack.slo.breadcrumbs.sloCreateLabel', { + defaultMessage: 'Create', + }), + }, + ], + { serverless } + ); useEffect(() => { if (hasRightLicense === false || permissions?.hasAllReadRequested === false) { diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slo_outdated_definitions/index.tsx b/x-pack/plugins/observability_solution/slo/public/pages/slo_outdated_definitions/index.tsx index a9afc480676c8..5a35061b464e5 100644 --- a/x-pack/plugins/observability_solution/slo/public/pages/slo_outdated_definitions/index.tsx +++ b/x-pack/plugins/observability_solution/slo/public/pages/slo_outdated_definitions/index.tsx @@ -23,26 +23,30 @@ import { OutdatedSloSearchBar } from './outdated_slo_search_bar'; export function SlosOutdatedDefinitions() { const { http: { basePath }, + serverless, } = useKibana().services; const { data: permissions } = usePermissions(); const { ObservabilityPageTemplate } = usePluginContext(); const { hasAtLeast } = useLicense(); - useBreadcrumbs([ - { - href: basePath.prepend(paths.slos), - text: i18n.translate('xpack.slo.breadcrumbs.slosLinkText', { - defaultMessage: 'SLOs', - }), - deepLinkId: 'slo', - }, - { - text: i18n.translate('xpack.slo.breadcrumbs.slosOutdatedDefinitions', { - defaultMessage: 'Outdated SLO Definitions', - }), - }, - ]); + useBreadcrumbs( + [ + { + href: basePath.prepend(paths.slos), + text: i18n.translate('xpack.slo.breadcrumbs.slosLinkText', { + defaultMessage: 'SLOs', + }), + deepLinkId: 'slo', + }, + { + text: i18n.translate('xpack.slo.breadcrumbs.slosOutdatedDefinitions', { + defaultMessage: 'Outdated SLO Definitions', + }), + }, + ], + { serverless } + ); const [search, setSearch] = useState(''); const [activePage, setActivePage] = useState(0); diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slo_settings/slo_settings.tsx b/x-pack/plugins/observability_solution/slo/public/pages/slo_settings/slo_settings.tsx index d2a2da4a5fafa..ca41c7561fb46 100644 --- a/x-pack/plugins/observability_solution/slo/public/pages/slo_settings/slo_settings.tsx +++ b/x-pack/plugins/observability_solution/slo/public/pages/slo_settings/slo_settings.tsx @@ -16,17 +16,21 @@ import { HeaderMenu } from '../../components/header_menu/header_menu'; export function SloSettingsPage() { const { http: { basePath }, + serverless, } = useKibana().services; const { ObservabilityPageTemplate } = usePluginContext(); - useBreadcrumbs([ - { - href: basePath.prepend(paths.slosSettings), - text: i18n.translate('xpack.slo.breadcrumbs.slosSettingsText', { - defaultMessage: 'SLOs Settings', - }), - }, - ]); + useBreadcrumbs( + [ + { + href: basePath.prepend(paths.slosSettings), + text: i18n.translate('xpack.slo.breadcrumbs.slosSettingsText', { + defaultMessage: 'SLOs Settings', + }), + }, + ], + { serverless } + ); return ( { if ((!isLoading && total === 0) || hasAtLeast('platinum') === false || isError) { diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/contexts/synthetics_settings_context.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/contexts/synthetics_settings_context.tsx index 14799683d96d5..d380d95c90aa4 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/contexts/synthetics_settings_context.tsx +++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/contexts/synthetics_settings_context.tsx @@ -38,7 +38,6 @@ export interface SyntheticsAppProps { setBadge: (badge?: ChromeBadge) => void; renderGlobalHelpControls(): void; commonlyUsedRanges: CommonlyUsedDateRange[]; - setBreadcrumbs: (crumbs: ChromeBreadcrumb[]) => void; appMountParameters: AppMountParameters; isDev: boolean; isServerless: boolean; @@ -89,7 +88,6 @@ export const SyntheticsSettingsContextProvider: React.FC diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/hooks/use_breadcrumbs.test.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/hooks/use_breadcrumbs.test.tsx index 5e524eca31bda..c97cefc194069 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/hooks/use_breadcrumbs.test.tsx +++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/hooks/use_breadcrumbs.test.tsx @@ -5,6 +5,7 @@ * 2.0. */ +import { coreMock } from '@kbn/core/public/mocks'; import { ChromeBreadcrumb } from '@kbn/core/public'; import { render } from '../utils/testing'; import React from 'react'; @@ -18,6 +19,8 @@ import { } from '../utils/url_params/get_supported_url_params'; import { makeBaseBreadcrumb, useBreadcrumbs } from './use_breadcrumbs'; import { SyntheticsSettingsContext } from '../contexts'; +import { BehaviorSubject } from 'rxjs'; +import { ChromeStyle } from '@kbn/core-chrome-browser'; describe('useBreadcrumbs', () => { it('sets the given breadcrumbs', () => { @@ -71,9 +74,10 @@ describe('useBreadcrumbs', () => { const urlParams: SyntheticsUrlParams = getSupportedUrlParams({}); expect(JSON.stringify(getBreadcrumbs())).toEqual( JSON.stringify( - makeBaseBreadcrumb('/app/synthetics', '/app/observability', urlParams, false).concat( - expectedCrumbs - ) + [ + { text: 'Observability', href: '/app/observability/overview' }, + ...makeBaseBreadcrumb('/app/synthetics', urlParams), + ].concat(expectedCrumbs) ) ); }); @@ -84,6 +88,8 @@ const mockCore: () => [() => ChromeBreadcrumb[], any] = () => { const get = () => { return breadcrumbObj; }; + const defaultCoreMock = coreMock.createStart(); + const core = { application: { getUrlForApp: (app: string) => @@ -91,6 +97,8 @@ const mockCore: () => [() => ChromeBreadcrumb[], any] = () => { navigateToUrl: jest.fn(), }, chrome: { + ...defaultCoreMock.chrome, + getChromeStyle$: () => new BehaviorSubject('classic').asObservable(), setBreadcrumbs: (newBreadcrumbs: ChromeBreadcrumb[]) => { breadcrumbObj = newBreadcrumbs; }, diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/hooks/use_breadcrumbs.ts b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/hooks/use_breadcrumbs.ts index 6d174f773e5a1..c311b08ff22f8 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/hooks/use_breadcrumbs.ts +++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/hooks/use_breadcrumbs.ts @@ -7,47 +7,20 @@ import { ChromeBreadcrumb } from '@kbn/core/public'; import { i18n } from '@kbn/i18n'; -import { MouseEvent, useContext, useEffect } from 'react'; +import { useMemo } from 'react'; import { EuiBreadcrumb } from '@elastic/eui'; import { useKibana } from '@kbn/kibana-react-plugin/public'; +import { useBreadcrumbs as useObservabilityBreadcrumbs } from '@kbn/observability-shared-plugin/public'; +import { ClientPluginsStart } from '../../../plugin'; import { SyntheticsUrlParams, stringifyUrlParams } from '../utils/url_params'; import { useUrlParams } from './use_url_params'; import { PLUGIN } from '../../../../common/constants/plugin'; -import { SyntheticsSettingsContext } from '../contexts'; const EMPTY_QUERY = '?'; -function handleBreadcrumbClick( - breadcrumbs: ChromeBreadcrumb[], - navigateToHref?: (url: string) => Promise -) { - return breadcrumbs.map((bc) => ({ - ...bc, - ...(bc.href - ? { - onClick: (event: MouseEvent) => { - if (navigateToHref && bc.href) { - event.preventDefault(); - navigateToHref(bc.href); - } - }, - } - : {}), - ...(bc['data-test-subj'] - ? { - 'data-test-subj': bc['data-test-subj'], - } - : { - 'data-test-subj': bc.href, - }), - })); -} - export const makeBaseBreadcrumb = ( uptimePath: string, - observabilityPath: string, - params?: SyntheticsUrlParams, - isServerless?: boolean + params?: SyntheticsUrlParams ): EuiBreadcrumb[] => { if (params) { const crumbParams: Partial = { ...params }; @@ -59,18 +32,6 @@ export const makeBaseBreadcrumb = ( const baseBreadcrumbs: EuiBreadcrumb[] = []; - // serverless Kibana has a curated UX flow, and "Observability" is already a given, - // thus we don't need to include it explicitly in the breadcrumb trail - if (!isServerless) { - baseBreadcrumbs.push({ - text: i18n.translate('xpack.synthetics.breadcrumbs.observabilityText', { - defaultMessage: 'Observability', - }), - href: observabilityPath, - 'data-test-subj': 'observabilityPathBreadcrumb', - }); - } - baseBreadcrumbs.push({ text: i18n.translate('xpack.synthetics.breadcrumbs.overviewBreadcrumbText', { defaultMessage: 'Synthetics', @@ -84,32 +45,12 @@ export const makeBaseBreadcrumb = ( export const useBreadcrumbs = (extraCrumbs: ChromeBreadcrumb[]) => { const params = useUrlParams()[0](); - const kibana = useKibana(); - const { setBreadcrumbs, isServerless } = useContext(SyntheticsSettingsContext); + const kibana = useKibana(); const syntheticsPath = kibana.services.application?.getUrlForApp(PLUGIN.SYNTHETICS_PLUGIN_ID) ?? ''; - const observabilityPath = - kibana.services.application?.getUrlForApp('observability-overview') ?? ''; - const navigate = kibana.services.application?.navigateToUrl; + const breadcrumbs = useMemo(() => { + return makeBaseBreadcrumb(syntheticsPath, params).concat(extraCrumbs); + }, [extraCrumbs, params, syntheticsPath]); - useEffect(() => { - if (setBreadcrumbs) { - setBreadcrumbs( - handleBreadcrumbClick( - makeBaseBreadcrumb(syntheticsPath, observabilityPath, params, isServerless).concat( - extraCrumbs - ), - navigate - ) - ); - } - }, [ - syntheticsPath, - observabilityPath, - extraCrumbs, - navigate, - params, - setBreadcrumbs, - isServerless, - ]); + useObservabilityBreadcrumbs(breadcrumbs, { serverless: kibana.services.serverless }); }; diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/render_app.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/render_app.tsx index 925f39fca7c07..19f97a6e50960 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/render_app.tsx +++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/render_app.tsx @@ -66,7 +66,6 @@ export const getSyntheticsAppProps = (): SyntheticsAppProps => { setBadge, appMountParameters, isServerless, - setBreadcrumbs: startPlugins.serverless?.setBreadcrumbs ?? coreStart.chrome.setBreadcrumbs, }; }; diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/utils/testing/rtl_helpers.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/utils/testing/rtl_helpers.tsx index af007700c4484..93ff3de42d360 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/utils/testing/rtl_helpers.tsx +++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/utils/testing/rtl_helpers.tsx @@ -7,7 +7,7 @@ import React, { ReactElement, ReactNode } from 'react'; import { i18n } from '@kbn/i18n'; -import { of } from 'rxjs'; +import { BehaviorSubject, of } from 'rxjs'; // eslint-disable-next-line import/no-extraneous-dependencies import { render as reactTestLibRender, @@ -29,6 +29,7 @@ import { KibanaContextProvider, KibanaServices } from '@kbn/kibana-react-plugin/ import { triggersActionsUiMock } from '@kbn/triggers-actions-ui-plugin/public/mocks'; import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; import { KibanaPageTemplate } from '@kbn/shared-ux-page-kibana-template'; +import { ChromeStyle } from '@kbn/core-chrome-browser'; import { mockState } from './__mocks__/synthetics_store.mock'; import { MountWithReduxProvider } from './helper_with_redux'; import { AppState } from '../../state'; @@ -166,6 +167,10 @@ export const mockCore: () => Partial = () => { ), }, + chrome: { + ...defaultCore.chrome, + getChromeStyle$: () => new BehaviorSubject('classic').asObservable(), + }, }; return core; diff --git a/x-pack/plugins/observability_solution/synthetics/tsconfig.json b/x-pack/plugins/observability_solution/synthetics/tsconfig.json index 24411ebdcb0c5..5df6d4257b4e9 100644 --- a/x-pack/plugins/observability_solution/synthetics/tsconfig.json +++ b/x-pack/plugins/observability_solution/synthetics/tsconfig.json @@ -104,7 +104,8 @@ "@kbn/babel-register", "@kbn/slo-plugin", "@kbn/ebt-tools", - "@kbn/alerting-types" + "@kbn/alerting-types", + "@kbn/core-chrome-browser" ], "exclude": ["target/**/*"] } diff --git a/x-pack/plugins/observability_solution/ux/public/application/application.test.tsx b/x-pack/plugins/observability_solution/ux/public/application/application.test.tsx index ef9c7df0a1a8d..2b9dd676eac17 100644 --- a/x-pack/plugins/observability_solution/ux/public/application/application.test.tsx +++ b/x-pack/plugins/observability_solution/ux/public/application/application.test.tsx @@ -17,6 +17,8 @@ import { coreMock } from '@kbn/core/public/mocks'; import { merge } from 'lodash'; import { UI_SETTINGS } from '@kbn/data-plugin/common'; import { embeddablePluginMock } from '@kbn/embeddable-plugin/public/mocks'; +import { BehaviorSubject } from 'rxjs'; +import { ChromeStyle } from '@kbn/core-chrome-browser'; jest.mock('../services/rest/data_view', () => ({ createStaticDataView: () => Promise.resolve(undefined), @@ -122,6 +124,10 @@ const mockCore = merge({}, coreStart, { return uiSettings[key]; }, }, + chrome: { + ...coreStart.chrome, + getChromeStyle$: () => new BehaviorSubject('classic').asObservable(), + }, }); export const mockApmPluginContextValue = { diff --git a/x-pack/plugins/observability_solution/ux/tsconfig.json b/x-pack/plugins/observability_solution/ux/tsconfig.json index 94da70641f150..b27a700aa9b1f 100644 --- a/x-pack/plugins/observability_solution/ux/tsconfig.json +++ b/x-pack/plugins/observability_solution/ux/tsconfig.json @@ -49,7 +49,8 @@ "@kbn/react-kibana-context-render", "@kbn/react-kibana-context-theme", "@kbn/search-types", - "@kbn/server-route-repository-utils" + "@kbn/server-route-repository-utils", + "@kbn/core-chrome-browser" ], "exclude": ["target/**/*"] } diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index ab75f1543cc33..e2d34ad004872 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -43613,7 +43613,6 @@ "xpack.synthetics.badge.readOnly.text": "Lecture seule", "xpack.synthetics.badge.readOnly.tooltip": "Enregistrement impossible", "xpack.synthetics.blocked": "Bloqué", - "xpack.synthetics.breadcrumbs.observabilityText": "Observabilité", "xpack.synthetics.breadcrumbs.overviewBreadcrumbText": "Synthetics", "xpack.synthetics.certificates.heading": "Certificats TLS ({total})", "xpack.synthetics.certificates.loading": "Chargement des certificats...", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index a77f0348b572f..21b2266f451c0 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -43351,7 +43351,6 @@ "xpack.synthetics.badge.readOnly.text": "読み取り専用", "xpack.synthetics.badge.readOnly.tooltip": "を保存できませんでした", "xpack.synthetics.blocked": "ブロック", - "xpack.synthetics.breadcrumbs.observabilityText": "Observability", "xpack.synthetics.breadcrumbs.overviewBreadcrumbText": "Synthetics", "xpack.synthetics.certificates.heading": "TLS証明書({total})", "xpack.synthetics.certificates.loading": "証明書を読み込んでいます...", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 2b13eacdad26e..0bfb50d722051 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -43401,7 +43401,6 @@ "xpack.synthetics.badge.readOnly.text": "只读", "xpack.synthetics.badge.readOnly.tooltip": "无法保存", "xpack.synthetics.blocked": "已阻止", - "xpack.synthetics.breadcrumbs.observabilityText": "Observability", "xpack.synthetics.breadcrumbs.overviewBreadcrumbText": "Synthetics", "xpack.synthetics.certificates.heading": "TLS 证书 ({total})", "xpack.synthetics.certificates.loading": "正在加载证书......", diff --git a/x-pack/test/functional/apps/infra/home_page.ts b/x-pack/test/functional/apps/infra/home_page.ts index 97d31c42b877a..f36b3394e2a89 100644 --- a/x-pack/test/functional/apps/infra/home_page.ts +++ b/x-pack/test/functional/apps/infra/home_page.ts @@ -144,7 +144,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const documentTitle = await browser.getTitle(); expect(documentTitle).to.contain( - 'Infrastructure Inventory - Infrastructure - Observability - Elastic' + 'Infrastructure inventory - Infrastructure - Observability - Elastic' ); }); @@ -459,7 +459,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await retry.tryForTime(5000, async () => { const documentTitle = await browser.getTitle(); expect(documentTitle).to.contain( - 'host-5 - Infrastructure Inventory - Infrastructure - Observability - Elastic' + 'host-5 - Infrastructure inventory - Infrastructure - Observability - Elastic' ); }); @@ -476,7 +476,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await retry.tryForTime(5000, async () => { const documentTitle = await browser.getTitle(); expect(documentTitle).to.contain( - 'pod-0 - Infrastructure Inventory - Infrastructure - Observability - Elastic' + 'pod-0 - Infrastructure inventory - Infrastructure - Observability - Elastic' ); }); @@ -494,7 +494,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await retry.tryForTime(5000, async () => { const documentTitle = await browser.getTitle(); expect(documentTitle).to.contain( - 'container-id-4 - Infrastructure Inventory - Infrastructure - Observability - Elastic' + 'container-id-4 - Infrastructure inventory - Infrastructure - Observability - Elastic' ); }); diff --git a/x-pack/test_serverless/functional/test_suites/observability/infra/infra.ts b/x-pack/test_serverless/functional/test_suites/observability/infra/infra.ts index 30cae6484f78b..b91ae6b09bde2 100644 --- a/x-pack/test_serverless/functional/test_suites/observability/infra/infra.ts +++ b/x-pack/test_serverless/functional/test_suites/observability/infra/infra.ts @@ -57,7 +57,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const documentTitle = await browser.getTitle(); expect(documentTitle).to.contain( - 'Infrastructure Inventory - Infrastructure - Observability - Elastic' + 'Infrastructure inventory - Infrastructure - Observability - Elastic' ); }); @@ -87,7 +87,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await retry.try(async () => { const documentTitle = await browser.getTitle(); expect(documentTitle).to.contain( - 'demo-stack-redis-01 - Infrastructure Inventory - Infrastructure - Observability - Elastic' + 'demo-stack-redis-01 - Infrastructure inventory - Infrastructure - Observability - Elastic' ); }); @@ -103,7 +103,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await retry.try(async () => { const documentTitle = await browser.getTitle(); expect(documentTitle).to.contain( - 'pod-0 - Infrastructure Inventory - Infrastructure - Observability - Elastic' + 'pod-0 - Infrastructure inventory - Infrastructure - Observability - Elastic' ); });