From 4437857b75c8408b920bd5349ac1bac3f93a46e5 Mon Sep 17 00:00:00 2001 From: Nathan L Smith Date: Thu, 17 Jun 2021 00:27:23 -0500 Subject: [PATCH] Refactor observability plugin breadcrumbs (#102290) Previously the observability plugin set the page title and breadcrumbs in the main app rendering component based on the `breadcrumb` property of the current route. In addition, there's a `useBreadcrumb` hook used by the UX app, exploratory view, and cases. The conflict between these was creating situations where neither would work and the breadcrumbs would just show "Kibana". Remove the breadcrumb properties from the routes and the main app breadcrumb handling and just use `useBreadcrumb` on all pages. Fixes #102131. --- .../public/application/index.tsx | 40 ++---- .../components/app/cases/case_view/index.tsx | 3 +- .../public/hooks/use_breadcrumbs.test.tsx | 116 ++++++++++++++++++ .../public/hooks/use_breadcrumbs.ts | 62 ++++------ .../public/pages/alerts/index.tsx | 9 ++ .../public/pages/cases/all_cases.tsx | 5 + .../public/pages/cases/configure_cases.tsx | 4 +- .../public/pages/cases/create_case.tsx | 4 +- .../observability/public/pages/cases/links.ts | 21 +++- .../public/pages/landing/index.tsx | 8 ++ .../public/pages/overview/index.tsx | 9 ++ .../observability/public/routes/index.tsx | 59 ++------- .../translations/translations/ja-JP.json | 6 - .../translations/translations/zh-CN.json | 6 - 14 files changed, 211 insertions(+), 141 deletions(-) create mode 100644 x-pack/plugins/observability/public/hooks/use_breadcrumbs.test.tsx diff --git a/x-pack/plugins/observability/public/application/index.tsx b/x-pack/plugins/observability/public/application/index.tsx index f8dce3ce1d487e..69ee6fa19cf0f7 100644 --- a/x-pack/plugins/observability/public/application/index.tsx +++ b/x-pack/plugins/observability/public/application/index.tsx @@ -6,30 +6,25 @@ */ import { i18n } from '@kbn/i18n'; -import React, { MouseEvent, useEffect } from 'react'; +import React from 'react'; import ReactDOM from 'react-dom'; import { Route, Router, Switch } from 'react-router-dom'; -import { EuiThemeProvider } from '../../../../../src/plugins/kibana_react/common'; +import { ConfigSchema } from '..'; import { AppMountParameters, APP_WRAPPER_CLASS, CoreStart } from '../../../../../src/core/public'; +import { EuiThemeProvider } from '../../../../../src/plugins/kibana_react/common'; import { KibanaContextProvider, RedirectAppLinks, } from '../../../../../src/plugins/kibana_react/public'; +import { Storage } from '../../../../../src/plugins/kibana_utils/public'; +import type { LazyObservabilityPageTemplateProps } from '../components/shared/page_template/lazy_page_template'; +import { HasDataContextProvider } from '../context/has_data_context'; import { PluginContext } from '../context/plugin_context'; -import { usePluginContext } from '../hooks/use_plugin_context'; import { useRouteParams } from '../hooks/use_route_params'; import { ObservabilityPublicPluginsStart } from '../plugin'; -import type { LazyObservabilityPageTemplateProps } from '../components/shared/page_template/lazy_page_template'; -import { HasDataContextProvider } from '../context/has_data_context'; -import { Breadcrumbs, routes } from '../routes'; -import { Storage } from '../../../../../src/plugins/kibana_utils/public'; -import { ConfigSchema } from '..'; +import { routes } from '../routes'; import { ObservabilityRuleTypeRegistry } from '../rules/create_observability_rule_type_registry'; -function getTitleFromBreadCrumbs(breadcrumbs: Breadcrumbs) { - return breadcrumbs.map(({ text }) => text).reverse(); -} - function App() { return ( <> @@ -38,27 +33,6 @@ function App() { const path = key as keyof typeof routes; const route = routes[path]; const Wrapper = () => { - const { core } = usePluginContext(); - - useEffect(() => { - const href = core.http.basePath.prepend('/app/observability'); - const breadcrumbs = [ - { - href, - text: i18n.translate('xpack.observability.observability.breadcrumb.', { - defaultMessage: 'Observability', - }), - onClick: (event: MouseEvent) => { - event.preventDefault(); - core.application.navigateToUrl(href); - }, - }, - ...route.breadcrumb, - ]; - core.chrome.setBreadcrumbs(breadcrumbs); - core.chrome.docTitle.change(getTitleFromBreadCrumbs(breadcrumbs)); - }, [core]); - const params = useRouteParams(path); return route.handler(params); }; diff --git a/x-pack/plugins/observability/public/components/app/cases/case_view/index.tsx b/x-pack/plugins/observability/public/components/app/cases/case_view/index.tsx index 3267f7bb17cce6..728333ac8c544f 100644 --- a/x-pack/plugins/observability/public/components/app/cases/case_view/index.tsx +++ b/x-pack/plugins/observability/public/components/app/cases/case_view/index.tsx @@ -7,6 +7,7 @@ import React, { useCallback, useState } from 'react'; import { + casesBreadcrumbs, getCaseDetailsUrl, getCaseDetailsUrlWithCommentId, getCaseUrl, @@ -17,7 +18,7 @@ import { Case } from '../../../../../../cases/common'; import { useFetchAlertData } from './helpers'; import { useKibana } from '../../../../utils/kibana_react'; import { CASES_APP_ID } from '../constants'; -import { casesBreadcrumbs, useBreadcrumbs } from '../../../../hooks/use_breadcrumbs'; +import { useBreadcrumbs } from '../../../../hooks/use_breadcrumbs'; interface Props { caseId: string; diff --git a/x-pack/plugins/observability/public/hooks/use_breadcrumbs.test.tsx b/x-pack/plugins/observability/public/hooks/use_breadcrumbs.test.tsx new file mode 100644 index 00000000000000..d033ecc2069cdf --- /dev/null +++ b/x-pack/plugins/observability/public/hooks/use_breadcrumbs.test.tsx @@ -0,0 +1,116 @@ +/* + * 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 { renderHook } from '@testing-library/react-hooks'; +import React, { ReactNode } from 'react'; +import { MemoryRouter } from 'react-router-dom'; +import { CoreStart } from '../../../../../src/core/public'; +import { createKibanaReactContext } from '../../../../../src/plugins/kibana_react/public'; +import { useBreadcrumbs } from './use_breadcrumbs'; + +const setBreadcrumbs = jest.fn(); +const setTitle = jest.fn(); +const kibanaServices = ({ + application: { getUrlForApp: () => {}, navigateToApp: () => {} }, + chrome: { setBreadcrumbs, docTitle: { change: setTitle } }, + uiSettings: { get: () => true }, +} as unknown) as Partial; +const KibanaContext = createKibanaReactContext(kibanaServices); + +function Wrapper({ children }: { children?: ReactNode }) { + return ( + + {children} + + ); +} + +describe('useBreadcrumbs', () => { + afterEach(() => { + setBreadcrumbs.mockClear(); + setTitle.mockClear(); + }); + + describe('when setBreadcrumbs and setTitle are not defined', () => { + it('does not set breadcrumbs or the title', () => { + renderHook(() => useBreadcrumbs([]), { + wrapper: ({ children }) => ( + + + } + > + {children} + + + ), + }); + + expect(setBreadcrumbs).not.toHaveBeenCalled(); + expect(setTitle).not.toHaveBeenCalled(); + }); + }); + + describe('with an empty array', () => { + it('sets the overview breadcrumb', () => { + renderHook(() => useBreadcrumbs([]), { wrapper: Wrapper }); + + expect(setBreadcrumbs).toHaveBeenCalledWith([ + { href: '/overview', onClick: expect.any(Function), text: 'Observability' }, + ]); + }); + + it('sets the overview title', () => { + renderHook(() => useBreadcrumbs([]), { wrapper: Wrapper }); + + expect(setTitle).toHaveBeenCalledWith(['Observability']); + }); + }); + + describe('given breadcrumbs', () => { + it('sets the breadcrumbs', () => { + renderHook( + () => + useBreadcrumbs([ + { text: 'One', href: '/one' }, + { + text: 'Two', + }, + ]), + { wrapper: Wrapper } + ); + + expect(setBreadcrumbs).toHaveBeenCalledWith([ + { href: '/overview', onClick: expect.any(Function), text: 'Observability' }, + { + href: '/one', + onClick: expect.any(Function), + text: 'One', + }, + { + text: 'Two', + }, + ]); + }); + + it('sets the title', () => { + renderHook( + () => + useBreadcrumbs([ + { text: 'One', href: '/one' }, + { + text: 'Two', + }, + ]), + { wrapper: Wrapper } + ); + + expect(setTitle).toHaveBeenCalledWith(['Two', 'One', 'Observability']); + }); + }); +}); diff --git a/x-pack/plugins/observability/public/hooks/use_breadcrumbs.ts b/x-pack/plugins/observability/public/hooks/use_breadcrumbs.ts index 090031e314fd1a..241a978d36948b 100644 --- a/x-pack/plugins/observability/public/hooks/use_breadcrumbs.ts +++ b/x-pack/plugins/observability/public/hooks/use_breadcrumbs.ts @@ -5,14 +5,13 @@ * 2.0. */ -import { ChromeBreadcrumb } from 'kibana/public'; import { i18n } from '@kbn/i18n'; +import { ChromeBreadcrumb } from 'kibana/public'; import { MouseEvent, useEffect } from 'react'; -import { EuiBreadcrumb } from '@elastic/eui'; -import { useQueryParams } from './use_query_params'; import { useKibana } from '../utils/kibana_react'; +import { useQueryParams } from './use_query_params'; -function handleBreadcrumbClick( +function addClickHandlers( breadcrumbs: ChromeBreadcrumb[], navigateToHref?: (url: string) => Promise ) { @@ -31,52 +30,37 @@ function handleBreadcrumbClick( })); } -export const makeBaseBreadcrumb = (href: string): EuiBreadcrumb => { - return { - text: i18n.translate('xpack.observability.breadcrumbs.observability', { - defaultMessage: 'Observability', - }), - href, - }; -}; -export const casesBreadcrumbs = { - cases: { - text: i18n.translate('xpack.observability.breadcrumbs.observability.cases', { - defaultMessage: 'Cases', - }), - }, - create: { - text: i18n.translate('xpack.observability.breadcrumbs.observability.cases.create', { - defaultMessage: 'Create', - }), - }, - configure: { - text: i18n.translate('xpack.observability.breadcrumbs.observability.cases.configure', { - defaultMessage: 'Configure', - }), - }, -}; +function getTitleFromBreadCrumbs(breadcrumbs: ChromeBreadcrumb[]) { + return breadcrumbs.map(({ text }) => text?.toString() ?? '').reverse(); +} + export const useBreadcrumbs = (extraCrumbs: ChromeBreadcrumb[]) => { const params = useQueryParams(); const { services: { - chrome: { setBreadcrumbs }, + chrome: { docTitle, setBreadcrumbs }, application: { getUrlForApp, navigateToUrl }, }, } = useKibana(); - + const setTitle = docTitle.change; const appPath = getUrlForApp('observability-overview') ?? ''; - const navigate = navigateToUrl; useEffect(() => { + const breadcrumbs = [ + { + text: i18n.translate('xpack.observability.breadcrumbs.observabilityLinkText', { + defaultMessage: 'Observability', + }), + href: appPath + '/overview', + }, + ...extraCrumbs, + ]; if (setBreadcrumbs) { - setBreadcrumbs( - handleBreadcrumbClick( - [makeBaseBreadcrumb(appPath + '/overview')].concat(extraCrumbs), - navigate - ) - ); + setBreadcrumbs(addClickHandlers(breadcrumbs, navigateToUrl)); + } + if (setTitle) { + setTitle(getTitleFromBreadCrumbs(breadcrumbs)); } - }, [appPath, extraCrumbs, navigate, params, setBreadcrumbs]); + }, [appPath, extraCrumbs, navigateToUrl, params, setBreadcrumbs, setTitle]); }; diff --git a/x-pack/plugins/observability/public/pages/alerts/index.tsx b/x-pack/plugins/observability/public/pages/alerts/index.tsx index bd926f3a326bf7..6f696a70665ce6 100644 --- a/x-pack/plugins/observability/public/pages/alerts/index.tsx +++ b/x-pack/plugins/observability/public/pages/alerts/index.tsx @@ -12,6 +12,7 @@ import { useHistory } from 'react-router-dom'; import { ParsedTechnicalFields } from '../../../../rule_registry/common/parse_technical_fields'; import type { AlertStatus } from '../../../common/typings'; import { ExperimentalBadge } from '../../components/shared/experimental_badge'; +import { useBreadcrumbs } from '../../hooks/use_breadcrumbs'; import { useFetcher } from '../../hooks/use_fetcher'; import { usePluginContext } from '../../hooks/use_plugin_context'; import { RouteParams } from '../../routes'; @@ -44,6 +45,14 @@ export function AlertsPage({ routeParams }: AlertsPageProps) { query: { rangeFrom = 'now-15m', rangeTo = 'now', kuery = '', status = 'open' }, } = routeParams; + useBreadcrumbs([ + { + text: i18n.translate('xpack.observability.breadcrumbs.alertsLinkText', { + defaultMessage: 'Alerts', + }), + }, + ]); + // In a future milestone we'll have a page dedicated to rule management in // observability. For now link to the settings page. const manageDetectionRulesHref = prepend( diff --git a/x-pack/plugins/observability/public/pages/cases/all_cases.tsx b/x-pack/plugins/observability/public/pages/cases/all_cases.tsx index 4131cdc40738f2..f73f3b4cf57d75 100644 --- a/x-pack/plugins/observability/public/pages/cases/all_cases.tsx +++ b/x-pack/plugins/observability/public/pages/cases/all_cases.tsx @@ -14,10 +14,15 @@ import { permissionsReadOnlyErrorMessage, CaseCallOut } from '../../components/a import { CaseFeatureNoPermissions } from './feature_no_permissions'; import { useGetUserCasesPermissions } from '../../hooks/use_get_user_cases_permissions'; import { usePluginContext } from '../../hooks/use_plugin_context'; +import { casesBreadcrumbs } from './links'; +import { useBreadcrumbs } from '../../hooks/use_breadcrumbs'; export const AllCasesPage = React.memo(() => { const userPermissions = useGetUserCasesPermissions(); const { ObservabilityPageTemplate } = usePluginContext(); + + useBreadcrumbs([casesBreadcrumbs.cases]); + return userPermissions == null || userPermissions?.read ? ( <> {userPermissions != null && !userPermissions?.crud && userPermissions?.read && ( diff --git a/x-pack/plugins/observability/public/pages/cases/configure_cases.tsx b/x-pack/plugins/observability/public/pages/cases/configure_cases.tsx index acc6bdf68fba75..2986c1ff34e11c 100644 --- a/x-pack/plugins/observability/public/pages/cases/configure_cases.tsx +++ b/x-pack/plugins/observability/public/pages/cases/configure_cases.tsx @@ -14,8 +14,8 @@ import { CASES_APP_ID, CASES_OWNER } from '../../components/app/cases/constants' import { useKibana } from '../../utils/kibana_react'; import { useGetUserCasesPermissions } from '../../hooks/use_get_user_cases_permissions'; import { usePluginContext } from '../../hooks/use_plugin_context'; -import { casesBreadcrumbs, useBreadcrumbs } from '../../hooks/use_breadcrumbs'; -import { getCaseUrl, useFormatUrl } from './links'; +import { useBreadcrumbs } from '../../hooks/use_breadcrumbs'; +import { casesBreadcrumbs, getCaseUrl, useFormatUrl } from './links'; const ButtonEmpty = styled(EuiButtonEmpty)` display: block; diff --git a/x-pack/plugins/observability/public/pages/cases/create_case.tsx b/x-pack/plugins/observability/public/pages/cases/create_case.tsx index d0e25e6263075b..11f6d62da61033 100644 --- a/x-pack/plugins/observability/public/pages/cases/create_case.tsx +++ b/x-pack/plugins/observability/public/pages/cases/create_case.tsx @@ -14,8 +14,8 @@ import { CASES_APP_ID } from '../../components/app/cases/constants'; import { useKibana } from '../../utils/kibana_react'; import { useGetUserCasesPermissions } from '../../hooks/use_get_user_cases_permissions'; import { usePluginContext } from '../../hooks/use_plugin_context'; -import { getCaseUrl, useFormatUrl } from './links'; -import { casesBreadcrumbs, useBreadcrumbs } from '../../hooks/use_breadcrumbs'; +import { casesBreadcrumbs, getCaseUrl, useFormatUrl } from './links'; +import { useBreadcrumbs } from '../../hooks/use_breadcrumbs'; const ButtonEmpty = styled(EuiButtonEmpty)` display: block; diff --git a/x-pack/plugins/observability/public/pages/cases/links.ts b/x-pack/plugins/observability/public/pages/cases/links.ts index 768d74ec4e7ee3..9b2f464a0e8471 100644 --- a/x-pack/plugins/observability/public/pages/cases/links.ts +++ b/x-pack/plugins/observability/public/pages/cases/links.ts @@ -5,10 +5,29 @@ * 2.0. */ -import { useCallback } from 'react'; +import { i18n } from '@kbn/i18n'; import { isEmpty } from 'lodash/fp'; +import { useCallback } from 'react'; import { useKibana } from '../../utils/kibana_react'; +export const casesBreadcrumbs = { + cases: { + text: i18n.translate('xpack.observability.breadcrumbs.casesLinkText', { + defaultMessage: 'Cases', + }), + }, + create: { + text: i18n.translate('xpack.observability.breadcrumbs.casesCreateLinkText', { + defaultMessage: 'Create', + }), + }, + configure: { + text: i18n.translate('xpack.observability.breadcrumbs.casesConfigureLinkText', { + defaultMessage: 'Configure', + }), + }, +}; + export const getCaseDetailsUrl = ({ id, subCaseId }: { id: string; subCaseId?: string }) => { if (subCaseId) { return `/${encodeURIComponent(id)}/sub-cases/${encodeURIComponent(subCaseId)}`; diff --git a/x-pack/plugins/observability/public/pages/landing/index.tsx b/x-pack/plugins/observability/public/pages/landing/index.tsx index 46c99bffbcc698..28d3784c65c4ae 100644 --- a/x-pack/plugins/observability/public/pages/landing/index.tsx +++ b/x-pack/plugins/observability/public/pages/landing/index.tsx @@ -21,6 +21,7 @@ import React, { useContext } from 'react'; import styled, { ThemeContext } from 'styled-components'; import { FleetPanel } from '../../components/app/fleet_panel'; import { ObservabilityHeaderMenu } from '../../components/app/header'; +import { useBreadcrumbs } from '../../hooks/use_breadcrumbs'; import { usePluginContext } from '../../hooks/use_plugin_context'; import { useTrackPageview } from '../../hooks/use_track_metric'; import { appsSection } from '../home/section'; @@ -33,6 +34,13 @@ const EuiCardWithoutPadding = styled(EuiCard)` export function LandingPage() { useTrackPageview({ app: 'observability-overview', path: 'landing' }); useTrackPageview({ app: 'observability-overview', path: 'landing', delay: 15000 }); + useBreadcrumbs([ + { + text: i18n.translate('xpack.observability.breadcrumbs.landingLinkText', { + defaultMessage: 'Getting started', + }), + }, + ]); const { core, ObservabilityPageTemplate } = usePluginContext(); const theme = useContext(ThemeContext); diff --git a/x-pack/plugins/observability/public/pages/overview/index.tsx b/x-pack/plugins/observability/public/pages/overview/index.tsx index 4cb6792d501952..89398ad16f1988 100644 --- a/x-pack/plugins/observability/public/pages/overview/index.tsx +++ b/x-pack/plugins/observability/public/pages/overview/index.tsx @@ -16,6 +16,7 @@ import { NewsFeed } from '../../components/app/news_feed'; import { Resources } from '../../components/app/resources'; import { AlertsSection } from '../../components/app/section/alerts'; import { DatePicker } from '../../components/shared/date_picker'; +import { useBreadcrumbs } from '../../hooks/use_breadcrumbs'; import { useFetcher } from '../../hooks/use_fetcher'; import { useHasData } from '../../hooks/use_has_data'; import { usePluginContext } from '../../hooks/use_plugin_context'; @@ -39,6 +40,14 @@ function calculateBucketSize({ start, end }: { start?: number; end?: number }) { export function OverviewPage({ routeParams }: Props) { useTrackPageview({ app: 'observability-overview', path: 'overview' }); useTrackPageview({ app: 'observability-overview', path: 'overview', delay: 15000 }); + useBreadcrumbs([ + { + text: i18n.translate('xpack.observability.breadcrumbs.overviewLinkText', { + defaultMessage: 'Overview', + }), + }, + ]); + const { core, ObservabilityPageTemplate } = usePluginContext(); const { relativeStart, relativeEnd, absoluteStart, absoluteEnd } = useTimeRange(); diff --git a/x-pack/plugins/observability/public/routes/index.tsx b/x-pack/plugins/observability/public/routes/index.tsx index a2a67a42bd166a..92f51aeff9bd63 100644 --- a/x-pack/plugins/observability/public/routes/index.tsx +++ b/x-pack/plugins/observability/public/routes/index.tsx @@ -5,21 +5,19 @@ * 2.0. */ -import React from 'react'; import * as t from 'io-ts'; -import { i18n } from '@kbn/i18n'; +import React from 'react'; +import { alertStatusRt } from '../../common/typings'; +import { ExploratoryViewPage } from '../components/shared/exploratory_view'; +import { AlertsPage } from '../pages/alerts'; +import { AllCasesPage } from '../pages/cases/all_cases'; +import { CaseDetailsPage } from '../pages/cases/case_details'; +import { ConfigureCasesPage } from '../pages/cases/configure_cases'; +import { CreateCasePage } from '../pages/cases/create_case'; import { HomePage } from '../pages/home'; import { LandingPage } from '../pages/landing'; import { OverviewPage } from '../pages/overview'; import { jsonRt } from './json_rt'; -import { AlertsPage } from '../pages/alerts'; -import { CreateCasePage } from '../pages/cases/create_case'; -import { ExploratoryViewPage } from '../components/shared/exploratory_view'; -import { CaseDetailsPage } from '../pages/cases/case_details'; -import { ConfigureCasesPage } from '../pages/cases/configure_cases'; -import { AllCasesPage } from '../pages/cases/all_cases'; -import { casesBreadcrumbs } from '../hooks/use_breadcrumbs'; -import { alertStatusRt } from '../../common/typings'; export type RouteParams = DecodeParams; @@ -27,8 +25,6 @@ type DecodeParams = { [key in keyof TParams]: TParams[key] extends t.Any ? t.TypeOf : never; }; -export type Breadcrumbs = Array<{ text: string }>; - export interface Params { query?: t.HasProps; path?: t.HasProps; @@ -40,26 +36,12 @@ export const routes = { return ; }, params: {}, - breadcrumb: [ - { - text: i18n.translate('xpack.observability.home.breadcrumb', { - defaultMessage: 'Overview', - }), - }, - ], }, '/landing': { handler: () => { return ; }, params: {}, - breadcrumb: [ - { - text: i18n.translate('xpack.observability.landing.breadcrumb', { - defaultMessage: 'Getting started', - }), - }, - ], }, '/overview': { handler: ({ query }: any) => { @@ -73,34 +55,24 @@ export const routes = { refreshInterval: jsonRt.pipe(t.number), }), }, - breadcrumb: [ - { - text: i18n.translate('xpack.observability.overview.breadcrumb', { - defaultMessage: 'Overview', - }), - }, - ], }, '/cases': { handler: () => { return ; }, params: {}, - breadcrumb: [casesBreadcrumbs.cases], }, '/cases/create': { handler: () => { return ; }, params: {}, - breadcrumb: [casesBreadcrumbs.cases, casesBreadcrumbs.create], }, '/cases/configure': { handler: () => { return ; }, params: {}, - breadcrumb: [casesBreadcrumbs.cases, casesBreadcrumbs.configure], }, '/cases/:detailName': { handler: () => { @@ -111,7 +83,6 @@ export const routes = { detailName: t.string, }), }, - breadcrumb: [casesBreadcrumbs.cases], }, '/alerts': { handler: (routeParams: any) => { @@ -127,13 +98,6 @@ export const routes = { refreshInterval: jsonRt.pipe(t.number), }), }, - breadcrumb: [ - { - text: i18n.translate('xpack.observability.alerts.breadcrumb', { - defaultMessage: 'Alerts', - }), - }, - ], }, '/exploratory-view': { handler: () => { @@ -147,12 +111,5 @@ export const routes = { refreshInterval: jsonRt.pipe(t.number), }), }, - breadcrumb: [ - { - text: i18n.translate('xpack.observability.overview.exploratoryView', { - defaultMessage: 'Analyze data', - }), - }, - ], }, }; diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index efe3345c7039fa..8eb19f0b0347d6 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -17233,7 +17233,6 @@ "xpack.monitoring.updateLicenseButtonLabel": "ライセンスを更新", "xpack.monitoring.updateLicenseTitle": "ライセンスの更新", "xpack.monitoring.useAvailableLicenseDescription": "すでに新しいライセンスがある場合は、今すぐアップロードしてください。", - "xpack.observability.alerts.breadcrumb": "アラート", "xpack.observability.alerts.manageDetectionRulesButtonLabel": "検出ルールの管理", "xpack.observability.alerts.searchBarPlaceholder": "\"domain\": \"ecommerce\" AND (\"service.name\":\"ProductCatalogService\" …)", "xpack.observability.alertsDisclaimerLinkText": "アラートとアクション", @@ -17254,7 +17253,6 @@ "xpack.observability.alertsTable.triggeredColumnDescription": "実行済み", "xpack.observability.alertsTable.viewInAppButtonLabel": "アプリで表示", "xpack.observability.alertsTitle": "アラート", - "xpack.observability.breadcrumbs.observability": "オブザーバビリティ", "xpack.observability.emptySection.apps.alert.description": "503 エラーが累積していますか?サービスは応答していますか?CPUとRAMの使用量が跳ね上がっていますか?このような警告を、事後にではなく、発生と同時に把握しましょう。", "xpack.observability.emptySection.apps.alert.link": "アラートの作成", "xpack.observability.emptySection.apps.alert.title": "アラートが見つかりません。", @@ -17330,15 +17328,12 @@ "xpack.observability.formatters.secondsTimeUnitLabel": "s", "xpack.observability.formatters.secondsTimeUnitLabelExtended": "秒", "xpack.observability.home.addData": "データの追加", - "xpack.observability.home.breadcrumb": "概要", "xpack.observability.home.getStatedButton": "使ってみる", "xpack.observability.home.sectionsubtitle": "ログ、メトリック、トレースを大規模に、1つのスタックにまとめて、環境内のあらゆる場所で生じるイベントの監視、分析、対応を行います。", "xpack.observability.home.sectionTitle": "エコシステム全体の一元的な可視性", - "xpack.observability.landing.breadcrumb": "はじめて使う", "xpack.observability.news.readFullStory": "詳細なストーリーを読む", "xpack.observability.news.title": "新機能", "xpack.observability.notAvailable": "N/A", - "xpack.observability.observability.breadcrumb.": "オブザーバビリティ", "xpack.observability.overview.alert.allTypes": "すべてのタイプ", "xpack.observability.overview.alert.appLink": "アラートを管理", "xpack.observability.overview.alert.view": "表示", @@ -17348,7 +17343,6 @@ "xpack.observability.overview.apm.services": "サービス", "xpack.observability.overview.apm.throughput": "スループット", "xpack.observability.overview.apm.title": "APM", - "xpack.observability.overview.breadcrumb": "概要", "xpack.observability.overview.exploratoryView": "調査ビュー", "xpack.observability.overview.exploratoryView.lensDisabled": "Lensアプリを使用できません。調査ビューを使用するには、Lensを有効にしてください。", "xpack.observability.overview.loadingObservability": "オブザーバビリティを読み込んでいます", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 5409da1c6c00b8..9fc6453ef2c3f6 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -17469,7 +17469,6 @@ "xpack.monitoring.updateLicenseButtonLabel": "更新许可证", "xpack.monitoring.updateLicenseTitle": "更新您的许可证", "xpack.monitoring.useAvailableLicenseDescription": "如果您已经持有新的许可证,请立即上传。", - "xpack.observability.alerts.breadcrumb": "告警", "xpack.observability.alerts.manageDetectionRulesButtonLabel": "管理检测规则", "xpack.observability.alerts.searchBarPlaceholder": "\"domain\": \"ecommerce\" AND (\"service.name\":\"ProductCatalogService\" …)", "xpack.observability.alertsDisclaimerLinkText": "告警和操作", @@ -17490,7 +17489,6 @@ "xpack.observability.alertsTable.triggeredColumnDescription": "已触发", "xpack.observability.alertsTable.viewInAppButtonLabel": "在应用中查看", "xpack.observability.alertsTitle": "告警", - "xpack.observability.breadcrumbs.observability": "可观测性", "xpack.observability.emptySection.apps.alert.description": "503 错误是否越来越多?服务是否响应?CPU 和 RAM 利用率是否激增?实时查看警告,而不是事后再进行剖析。", "xpack.observability.emptySection.apps.alert.link": "创建告警", "xpack.observability.emptySection.apps.alert.title": "未找到告警。", @@ -17566,15 +17564,12 @@ "xpack.observability.formatters.secondsTimeUnitLabel": "s", "xpack.observability.formatters.secondsTimeUnitLabelExtended": "秒", "xpack.observability.home.addData": "添加数据", - "xpack.observability.home.breadcrumb": "概览", "xpack.observability.home.getStatedButton": "开始使用", "xpack.observability.home.sectionsubtitle": "通过根据需要将日志、指标和跟踪都置于单个堆栈上,来监测、分析和响应环境中任何位置发生的事件。", "xpack.observability.home.sectionTitle": "整个生态系统的统一可见性", - "xpack.observability.landing.breadcrumb": "入门", "xpack.observability.news.readFullStory": "详细了解", "xpack.observability.news.title": "最新动态", "xpack.observability.notAvailable": "不可用", - "xpack.observability.observability.breadcrumb.": "可观测性", "xpack.observability.overview.alert.allTypes": "所有类型", "xpack.observability.overview.alert.appLink": "管理告警", "xpack.observability.overview.alert.view": "查看", @@ -17584,7 +17579,6 @@ "xpack.observability.overview.apm.services": "服务", "xpack.observability.overview.apm.throughput": "吞吐量", "xpack.observability.overview.apm.title": "APM", - "xpack.observability.overview.breadcrumb": "概览", "xpack.observability.overview.exploratoryView": "浏览视图", "xpack.observability.overview.exploratoryView.lensDisabled": "Lens 应用不可用,请启用 Lens 以使用浏览视图。", "xpack.observability.overview.loadingObservability": "正在加载可观测性",