From ac40e89130da31f48369af764e7e10871f1d512f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loix?= Date: Mon, 14 Oct 2024 12:42:41 +0100 Subject: [PATCH 01/10] Allow project breadcrumb to be declared along with classic ones --- .../src/chrome_service.tsx | 23 +++++++++++++++--- .../src/project_navigation/breadcrumbs.tsx | 9 ++++--- .../project_navigation_service.ts | 7 +++--- .../core-chrome-browser-internal/src/types.ts | 4 ++-- .../core/chrome/core-chrome-browser/index.ts | 2 +- .../core-chrome-browser/src/breadcrumb.ts | 24 +++++++++++++++++++ .../core-chrome-browser/src/contracts.ts | 8 +++++-- .../chrome/core-chrome-browser/src/index.ts | 7 ++++-- .../src/project_navigation.ts | 4 ---- 9 files changed, 65 insertions(+), 23 deletions(-) diff --git a/packages/core/chrome/core-chrome-browser-internal/src/chrome_service.tsx b/packages/core/chrome/core-chrome-browser-internal/src/chrome_service.tsx index 8ae1b7fb61cc5..75af9338225fe 100644 --- a/packages/core/chrome/core-chrome-browser-internal/src/chrome_service.tsx +++ b/packages/core/chrome/core-chrome-browser-internal/src/chrome_service.tsx @@ -27,6 +27,7 @@ import type { ChromeNavLink, ChromeBadge, ChromeBreadcrumb, + ChromeSetBreadcrumbsParams, ChromeBreadcrumbsAppendExtension, ChromeGlobalHelpExtensionMenuLink, ChromeHelpExtension, @@ -354,6 +355,24 @@ export class ChromeService { projectNavigation.setProjectBreadcrumbs(breadcrumbs, params); }; + const setClassicBreadcrumbs = ( + newBreadcrumbs: ChromeBreadcrumb[], + { + project: { isSameAsClassic = false, value: _projectValue, absolute = false } = {}, + }: ChromeSetBreadcrumbsParams = {} + ) => { + if (isSameAsClassic && _projectValue !== undefined) { + throw new Error('`isSameAsClassic` and `value` cannot be set at the same time.'); + } + const type = chromeStyleSubject$.getValue(); + const projectValue = isSameAsClassic ? newBreadcrumbs : _projectValue; + if (type === 'project') { + setProjectBreadcrumbs(projectValue ?? [], { absolute }); + } else { + breadcrumbs$.next(newBreadcrumbs); + } + }; + const setProjectHome = (homeHref: string) => { validateChromeStyle(); projectNavigation.setProjectHome(homeHref); @@ -507,9 +526,7 @@ export class ChromeService { getBreadcrumbs$: () => breadcrumbs$.pipe(takeUntil(this.stop$)), - setBreadcrumbs: (newBreadcrumbs: ChromeBreadcrumb[]) => { - breadcrumbs$.next(newBreadcrumbs); - }, + setBreadcrumbs: setClassicBreadcrumbs, getBreadcrumbsAppendExtension$: () => breadcrumbsAppendExtension$.pipe(takeUntil(this.stop$)), diff --git a/packages/core/chrome/core-chrome-browser-internal/src/project_navigation/breadcrumbs.tsx b/packages/core/chrome/core-chrome-browser-internal/src/project_navigation/breadcrumbs.tsx index fe247f44fbadc..d6bc89deb2ce5 100644 --- a/packages/core/chrome/core-chrome-browser-internal/src/project_navigation/breadcrumbs.tsx +++ b/packages/core/chrome/core-chrome-browser-internal/src/project_navigation/breadcrumbs.tsx @@ -11,7 +11,6 @@ import React from 'react'; import { EuiContextMenuPanel, EuiContextMenuItem, EuiButtonEmpty } from '@elastic/eui'; import type { AppDeepLinkId, - ChromeProjectBreadcrumb, ChromeProjectNavigationNode, ChromeSetProjectBreadcrumbsParams, ChromeBreadcrumb, @@ -30,14 +29,14 @@ export function buildBreadcrumbs({ }: { projectName?: string; projectBreadcrumbs: { - breadcrumbs: ChromeProjectBreadcrumb[]; + breadcrumbs: ChromeBreadcrumb[]; params: ChromeSetProjectBreadcrumbsParams; }; chromeBreadcrumbs: ChromeBreadcrumb[]; cloudLinks: CloudLinks; activeNodes: ChromeProjectNavigationNode[][]; isServerless: boolean; -}): ChromeProjectBreadcrumb[] { +}): ChromeBreadcrumb[] { const rootCrumb = buildRootCrumb({ projectName, cloudLinks, @@ -54,7 +53,7 @@ export function buildBreadcrumbs({ (n) => Boolean(n.title) && n.breadcrumbStatus !== 'hidden' ); const navBreadcrumbs = navBreadcrumbPath.map( - (node): ChromeProjectBreadcrumb => ({ + (node): ChromeBreadcrumb => ({ href: node.deepLink?.url ?? node.href, deepLinkId: node.deepLink?.id as AppDeepLinkId, text: node.title, @@ -99,7 +98,7 @@ function buildRootCrumb({ projectName?: string; cloudLinks: CloudLinks; isServerless: boolean; -}): ChromeProjectBreadcrumb { +}): ChromeBreadcrumb { if (isServerless) { return { text: diff --git a/packages/core/chrome/core-chrome-browser-internal/src/project_navigation/project_navigation_service.ts b/packages/core/chrome/core-chrome-browser-internal/src/project_navigation/project_navigation_service.ts index 6f77705069eaf..85c3fd1905adb 100644 --- a/packages/core/chrome/core-chrome-browser-internal/src/project_navigation/project_navigation_service.ts +++ b/packages/core/chrome/core-chrome-browser-internal/src/project_navigation/project_navigation_service.ts @@ -11,7 +11,6 @@ import { InternalApplicationStart } from '@kbn/core-application-browser-internal import type { ChromeNavLinks, SideNavComponent, - ChromeProjectBreadcrumb, ChromeBreadcrumb, ChromeSetProjectBreadcrumbsParams, ChromeProjectNavigationNode, @@ -80,7 +79,7 @@ export class ProjectNavigationService { ); private projectBreadcrumbs$ = new BehaviorSubject<{ - breadcrumbs: ChromeProjectBreadcrumb[]; + breadcrumbs: ChromeBreadcrumb[]; params: ChromeSetProjectBreadcrumbsParams; }>({ breadcrumbs: [], params: { absolute: false } }); private readonly stop$ = new ReplaySubject(1); @@ -153,7 +152,7 @@ export class ProjectNavigationService { return this.customProjectSideNavComponent$.asObservable(); }, setProjectBreadcrumbs: ( - breadcrumbs: ChromeProjectBreadcrumb | ChromeProjectBreadcrumb[], + breadcrumbs: ChromeBreadcrumb | ChromeBreadcrumb[], params?: Partial ) => { this.projectBreadcrumbs$.next({ @@ -161,7 +160,7 @@ export class ProjectNavigationService { params: { absolute: false, ...params }, }); }, - getProjectBreadcrumbs$: (): Observable => { + getProjectBreadcrumbs$: (): Observable => { return combineLatest([ this.projectBreadcrumbs$, this.activeNodes$, diff --git a/packages/core/chrome/core-chrome-browser-internal/src/types.ts b/packages/core/chrome/core-chrome-browser-internal/src/types.ts index a958eb59cd5f1..2c43bf128c44f 100644 --- a/packages/core/chrome/core-chrome-browser-internal/src/types.ts +++ b/packages/core/chrome/core-chrome-browser-internal/src/types.ts @@ -9,8 +9,8 @@ import type { ChromeStart, + ChromeBreadcrumb, SideNavComponent, - ChromeProjectBreadcrumb, ChromeSetProjectBreadcrumbsParams, ChromeProjectNavigationNode, AppDeepLinkId, @@ -95,7 +95,7 @@ export interface InternalChromeStart extends ChromeStart { * Use {@link ServerlessPluginStart.setBreadcrumbs} to set project breadcrumbs. */ setBreadcrumbs( - breadcrumbs: ChromeProjectBreadcrumb[] | ChromeProjectBreadcrumb, + breadcrumbs: ChromeBreadcrumb[] | ChromeBreadcrumb, params?: Partial ): void; diff --git a/packages/core/chrome/core-chrome-browser/index.ts b/packages/core/chrome/core-chrome-browser/index.ts index 4400c5e7d2b3f..afb2050d12e80 100644 --- a/packages/core/chrome/core-chrome-browser/index.ts +++ b/packages/core/chrome/core-chrome-browser/index.ts @@ -12,6 +12,7 @@ export type { AppId, ChromeBadge, ChromeBreadcrumb, + ChromeSetBreadcrumbsParams, ChromeBreadcrumbsAppendExtension, ChromeDocTitle, ChromeGlobalHelpExtensionMenuLink, @@ -41,7 +42,6 @@ export type { SideNavCompProps, SideNavComponent, SideNavNodeStatus, - ChromeProjectBreadcrumb, ChromeSetProjectBreadcrumbsParams, NodeDefinition, NodeDefinitionWithChildren, diff --git a/packages/core/chrome/core-chrome-browser/src/breadcrumb.ts b/packages/core/chrome/core-chrome-browser/src/breadcrumb.ts index 0a655b7706308..49f204006ad14 100644 --- a/packages/core/chrome/core-chrome-browser/src/breadcrumb.ts +++ b/packages/core/chrome/core-chrome-browser/src/breadcrumb.ts @@ -24,3 +24,27 @@ export interface ChromeBreadcrumb extends EuiBreadcrumb { export interface ChromeBreadcrumbsAppendExtension { content: MountPoint; } + +/** @public */ +export interface ChromeSetBreadcrumbsParams { + /** + * Declare the breadcrumbs for the project/solution type navigation in stateful. + * Those breadcrumbs correspond to the serverless breadcrumbs declaration. + */ + project?: { + /** + * If the same breadcrumb should be used as in classic, set this flag to true. + * @default: false + */ + isSameAsClassic?: boolean; + /** + * The breadcrumb value to set. Can be a single breadcrumb or an array of breadcrumbs. + */ + value?: ChromeBreadcrumb | ChromeBreadcrumb[]; + /** + * Indicates whether the breadcrumb should be absolute (replaces the full path) or relative. + * @default false + */ + absolute?: boolean; + }; +} diff --git a/packages/core/chrome/core-chrome-browser/src/contracts.ts b/packages/core/chrome/core-chrome-browser/src/contracts.ts index aa2e4cf23ebbb..f5b5d1f0eaf12 100644 --- a/packages/core/chrome/core-chrome-browser/src/contracts.ts +++ b/packages/core/chrome/core-chrome-browser/src/contracts.ts @@ -13,7 +13,11 @@ import type { ChromeRecentlyAccessed } from './recently_accessed'; import type { ChromeDocTitle } from './doc_title'; import type { ChromeHelpMenuLink, ChromeNavControls } from './nav_controls'; import type { ChromeHelpExtension } from './help_extension'; -import type { ChromeBreadcrumb, ChromeBreadcrumbsAppendExtension } from './breadcrumb'; +import type { + ChromeBreadcrumb, + ChromeBreadcrumbsAppendExtension, + ChromeSetBreadcrumbsParams, +} from './breadcrumb'; import type { ChromeBadge, ChromeStyle, ChromeUserBanner } from './types'; import type { ChromeGlobalHelpExtensionMenuLink } from './help_extension'; import type { PanelSelectedNode } from './project_navigation'; @@ -84,7 +88,7 @@ export interface ChromeStart { /** * Override the current set of breadcrumbs */ - setBreadcrumbs(newBreadcrumbs: ChromeBreadcrumb[]): void; + setBreadcrumbs(newBreadcrumbs: ChromeBreadcrumb[], params?: ChromeSetBreadcrumbsParams): void; /** * Get an observable of the current extension appended to breadcrumbs diff --git a/packages/core/chrome/core-chrome-browser/src/index.ts b/packages/core/chrome/core-chrome-browser/src/index.ts index 7247bfe69710a..efc2fb5636d84 100644 --- a/packages/core/chrome/core-chrome-browser/src/index.ts +++ b/packages/core/chrome/core-chrome-browser/src/index.ts @@ -7,7 +7,11 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -export type { ChromeBreadcrumbsAppendExtension, ChromeBreadcrumb } from './breadcrumb'; +export type { + ChromeBreadcrumbsAppendExtension, + ChromeBreadcrumb, + ChromeSetBreadcrumbsParams, +} from './breadcrumb'; export type { ChromeStart } from './contracts'; export type { ChromeDocTitle } from './doc_title'; export type { @@ -42,7 +46,6 @@ export type { SideNavComponent, SideNavNodeStatus, ChromeSetProjectBreadcrumbsParams, - ChromeProjectBreadcrumb, NodeDefinition, NodeDefinitionWithChildren, RenderAs as NodeRenderAs, diff --git a/packages/core/chrome/core-chrome-browser/src/project_navigation.ts b/packages/core/chrome/core-chrome-browser/src/project_navigation.ts index 417deea8e003e..3e6afeb8f6117 100644 --- a/packages/core/chrome/core-chrome-browser/src/project_navigation.ts +++ b/packages/core/chrome/core-chrome-browser/src/project_navigation.ts @@ -39,7 +39,6 @@ import type { AppId as SecurityApp, DeepLinkId as SecurityLink } from '@kbn/deep import type { AppId as FleetApp, DeepLinkId as FleetLink } from '@kbn/deeplinks-fleet'; import type { AppId as SharedApp, DeepLinkId as SharedLink } from '@kbn/deeplinks-shared'; -import type { ChromeBreadcrumb } from './breadcrumb'; import type { ChromeNavLink } from './nav_links'; import type { ChromeRecentlyAccessedHistoryItem } from './recently_accessed'; @@ -262,9 +261,6 @@ export interface SideNavCompProps { /** @public */ export type SideNavComponent = ComponentType; -/** @public */ -export type ChromeProjectBreadcrumb = ChromeBreadcrumb; - /** @public */ export interface ChromeSetProjectBreadcrumbsParams { absolute: boolean; From 30623a5b0f7945d7fbc508c1e2eebeacb2fa4e7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loix?= Date: Mon, 14 Oct 2024 14:30:30 +0100 Subject: [PATCH 02/10] Update dashboard breadcrumb for solution nav --- .../public/dashboard_top_nav/internal_dashboard_top_nav.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/plugins/dashboard/public/dashboard_top_nav/internal_dashboard_top_nav.tsx b/src/plugins/dashboard/public/dashboard_top_nav/internal_dashboard_top_nav.tsx index bdbb506dfc713..6ca2298272c08 100644 --- a/src/plugins/dashboard/public/dashboard_top_nav/internal_dashboard_top_nav.tsx +++ b/src/plugins/dashboard/public/dashboard_top_nav/internal_dashboard_top_nav.tsx @@ -189,7 +189,10 @@ export function InternalDashboardTopNav({ }, }, ...dashboardTitleBreadcrumbs, - ]) + ]), + { + project: { value: dashboardTitleBreadcrumbs }, + } ); } }, [redirectTo, dashboardTitle, dashboardApi, viewMode, customLeadingBreadCrumbs]); From 6b6436fa9609fc8030c70d61827f583afbabd660 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loix?= Date: Mon, 14 Oct 2024 14:36:11 +0100 Subject: [PATCH 03/10] Update security breadcrumb for solution nav --- .../security_solution_ess/public/navigation/breadcrumbs.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution_ess/public/navigation/breadcrumbs.ts b/x-pack/plugins/security_solution_ess/public/navigation/breadcrumbs.ts index f0305cfb95511..476be6172d597 100644 --- a/x-pack/plugins/security_solution_ess/public/navigation/breadcrumbs.ts +++ b/x-pack/plugins/security_solution_ess/public/navigation/breadcrumbs.ts @@ -10,6 +10,10 @@ import type { Services } from '../common/services'; export const subscribeBreadcrumbs = (services: Services) => { const { securitySolution, chrome } = services; securitySolution.getBreadcrumbsNav$().subscribe((breadcrumbsNav) => { - chrome.setBreadcrumbs([...breadcrumbsNav.leading, ...breadcrumbsNav.trailing]); + chrome.setBreadcrumbs([...breadcrumbsNav.leading, ...breadcrumbsNav.trailing], { + project: { + value: breadcrumbsNav.trailing, + }, + }); }); }; From 4afdb2bc3e870eb86cb1508ffc984e2dba563185 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loix?= Date: Mon, 14 Oct 2024 16:06:30 +0100 Subject: [PATCH 04/10] Always set both classic and project breadcrumbs array --- .../core-chrome-browser-internal/src/chrome_service.tsx | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/core/chrome/core-chrome-browser-internal/src/chrome_service.tsx b/packages/core/chrome/core-chrome-browser-internal/src/chrome_service.tsx index 75af9338225fe..65dd290091b3f 100644 --- a/packages/core/chrome/core-chrome-browser-internal/src/chrome_service.tsx +++ b/packages/core/chrome/core-chrome-browser-internal/src/chrome_service.tsx @@ -364,13 +364,9 @@ export class ChromeService { if (isSameAsClassic && _projectValue !== undefined) { throw new Error('`isSameAsClassic` and `value` cannot be set at the same time.'); } - const type = chromeStyleSubject$.getValue(); const projectValue = isSameAsClassic ? newBreadcrumbs : _projectValue; - if (type === 'project') { - setProjectBreadcrumbs(projectValue ?? [], { absolute }); - } else { - breadcrumbs$.next(newBreadcrumbs); - } + breadcrumbs$.next(newBreadcrumbs); + setProjectBreadcrumbs(projectValue ?? [], { absolute }); }; const setProjectHome = (homeHref: string) => { From 6e795d1a99a03def1e813fbe419ec3cb0bbc6803 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loix?= Date: Mon, 14 Oct 2024 16:07:23 +0100 Subject: [PATCH 05/10] Update management breadcrumb for solution nav --- src/plugins/management/public/plugin.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plugins/management/public/plugin.tsx b/src/plugins/management/public/plugin.tsx index 8f8f0f6c0339b..97778792316ea 100644 --- a/src/plugins/management/public/plugin.tsx +++ b/src/plugins/management/public/plugin.tsx @@ -131,7 +131,9 @@ export class ManagementPlugin const [, ...trailingBreadcrumbs] = newBreadcrumbs; deps.serverless.setBreadcrumbs(trailingBreadcrumbs); } else { - coreStart.chrome.setBreadcrumbs(newBreadcrumbs); + coreStart.chrome.setBreadcrumbs(newBreadcrumbs, { + project: { value: newBreadcrumbs, absolute: true }, + }); } }, isSidebarEnabled$: managementPlugin.isSidebarEnabled$, From 56f088d3a4a8036d7060a4c6f157d9c9cb3362f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loix?= Date: Mon, 14 Oct 2024 16:32:33 +0100 Subject: [PATCH 06/10] Remove isSameAsClassic option --- .../src/chrome_service.tsx | 13 +++++-------- .../chrome/core-chrome-browser/src/breadcrumb.ts | 7 +------ 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/packages/core/chrome/core-chrome-browser-internal/src/chrome_service.tsx b/packages/core/chrome/core-chrome-browser-internal/src/chrome_service.tsx index 65dd290091b3f..2e7e593fe1998 100644 --- a/packages/core/chrome/core-chrome-browser-internal/src/chrome_service.tsx +++ b/packages/core/chrome/core-chrome-browser-internal/src/chrome_service.tsx @@ -357,16 +357,13 @@ export class ChromeService { const setClassicBreadcrumbs = ( newBreadcrumbs: ChromeBreadcrumb[], - { - project: { isSameAsClassic = false, value: _projectValue, absolute = false } = {}, - }: ChromeSetBreadcrumbsParams = {} + { project }: ChromeSetBreadcrumbsParams = {} ) => { - if (isSameAsClassic && _projectValue !== undefined) { - throw new Error('`isSameAsClassic` and `value` cannot be set at the same time.'); - } - const projectValue = isSameAsClassic ? newBreadcrumbs : _projectValue; breadcrumbs$.next(newBreadcrumbs); - setProjectBreadcrumbs(projectValue ?? [], { absolute }); + if (project) { + const { value: projectValue, absolute = false } = project; + setProjectBreadcrumbs(projectValue ?? [], { absolute }); + } }; const setProjectHome = (homeHref: string) => { diff --git a/packages/core/chrome/core-chrome-browser/src/breadcrumb.ts b/packages/core/chrome/core-chrome-browser/src/breadcrumb.ts index 49f204006ad14..c0067030b7b0c 100644 --- a/packages/core/chrome/core-chrome-browser/src/breadcrumb.ts +++ b/packages/core/chrome/core-chrome-browser/src/breadcrumb.ts @@ -32,15 +32,10 @@ export interface ChromeSetBreadcrumbsParams { * Those breadcrumbs correspond to the serverless breadcrumbs declaration. */ project?: { - /** - * If the same breadcrumb should be used as in classic, set this flag to true. - * @default: false - */ - isSameAsClassic?: boolean; /** * The breadcrumb value to set. Can be a single breadcrumb or an array of breadcrumbs. */ - value?: ChromeBreadcrumb | ChromeBreadcrumb[]; + value: ChromeBreadcrumb | ChromeBreadcrumb[]; /** * Indicates whether the breadcrumb should be absolute (replaces the full path) or relative. * @default false From 92f8330a508d72aad6152a6189367630ce257b8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loix?= Date: Mon, 14 Oct 2024 16:56:08 +0100 Subject: [PATCH 07/10] Add jest test --- .../src/chrome_service.test.tsx | 31 ++++++++++++++++++- .../src/chrome_service.tsx | 1 + .../core-chrome-browser-internal/src/types.ts | 3 ++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/packages/core/chrome/core-chrome-browser-internal/src/chrome_service.test.tsx b/packages/core/chrome/core-chrome-browser-internal/src/chrome_service.test.tsx index 7d7122e7387ce..4994302c2e756 100644 --- a/packages/core/chrome/core-chrome-browser-internal/src/chrome_service.test.tsx +++ b/packages/core/chrome/core-chrome-browser-internal/src/chrome_service.test.tsx @@ -392,7 +392,7 @@ describe('start', () => { describe('breadcrumbs', () => { it('updates/emits the current set of breadcrumbs', async () => { const { chrome, service } = await start(); - const promise = chrome.getBreadcrumbs$().pipe(toArray()).toPromise(); + const promise = firstValueFrom(chrome.getBreadcrumbs$().pipe(toArray())); chrome.setBreadcrumbs([{ text: 'foo' }, { text: 'bar' }]); chrome.setBreadcrumbs([{ text: 'foo' }]); @@ -425,6 +425,35 @@ describe('start', () => { ] `); }); + + it('allows the project breadcrumb to also be set', async () => { + const { chrome } = await start(); + + chrome.setBreadcrumbs([{ text: 'foo' }, { text: 'bar' }]); // only setting the classic breadcrumbs + + { + const breadcrumbs = await firstValueFrom(chrome.project.getBreadcrumbs$()); + expect(breadcrumbs.length).toBe(1); + expect(breadcrumbs[0]).toMatchObject({ + 'data-test-subj': 'deploymentCrumb', + }); + } + + chrome.setBreadcrumbs([{ text: 'foo' }, { text: 'bar' }], { + project: { value: [{ text: 'baz' }] }, // also setting the project breadcrumb + }); + + { + const breadcrumbs = await firstValueFrom(chrome.project.getBreadcrumbs$()); + expect(breadcrumbs.length).toBe(2); + expect(breadcrumbs[0]).toMatchObject({ + 'data-test-subj': 'deploymentCrumb', + }); + expect(breadcrumbs[1]).toEqual({ + text: 'baz', // the project breadcrumb + }); + } + }); }); describe('breadcrumbsAppendExtension$', () => { diff --git a/packages/core/chrome/core-chrome-browser-internal/src/chrome_service.tsx b/packages/core/chrome/core-chrome-browser-internal/src/chrome_service.tsx index 2e7e593fe1998..5d86209ec8800 100644 --- a/packages/core/chrome/core-chrome-browser-internal/src/chrome_service.tsx +++ b/packages/core/chrome/core-chrome-browser-internal/src/chrome_service.tsx @@ -596,6 +596,7 @@ export class ChromeService { getNavigationTreeUi$: () => projectNavigation.getNavigationTreeUi$(), setSideNavComponent: setProjectSideNavComponent, setBreadcrumbs: setProjectBreadcrumbs, + getBreadcrumbs$: projectNavigation.getProjectBreadcrumbs$.bind(projectNavigation), getActiveNavigationNodes$: () => projectNavigation.getActiveNodes$(), updateSolutionNavigations: projectNavigation.updateSolutionNavigations, changeActiveSolutionNavigation: projectNavigation.changeActiveSolutionNavigation, diff --git a/packages/core/chrome/core-chrome-browser-internal/src/types.ts b/packages/core/chrome/core-chrome-browser-internal/src/types.ts index 2c43bf128c44f..0e6bec4d2678c 100644 --- a/packages/core/chrome/core-chrome-browser-internal/src/types.ts +++ b/packages/core/chrome/core-chrome-browser-internal/src/types.ts @@ -87,6 +87,9 @@ export interface InternalChromeStart extends ChromeStart { */ setSideNavComponent(component: SideNavComponent | null): void; + /** Get an Observable of the current project breadcrumbs */ + getBreadcrumbs$(): Observable; + /** * Set project breadcrumbs * @param breadcrumbs From c8aced476514b83f969d1bf26dc29c05a45d8941 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loix?= Date: Tue, 15 Oct 2024 10:23:19 +0100 Subject: [PATCH 08/10] Fix TS issue --- .../chrome/core-chrome-browser-mocks/src/chrome_service.mock.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/core/chrome/core-chrome-browser-mocks/src/chrome_service.mock.ts b/packages/core/chrome/core-chrome-browser-mocks/src/chrome_service.mock.ts index 144002ee94547..6be7bb68907eb 100644 --- a/packages/core/chrome/core-chrome-browser-mocks/src/chrome_service.mock.ts +++ b/packages/core/chrome/core-chrome-browser-mocks/src/chrome_service.mock.ts @@ -84,6 +84,7 @@ const createStartContractMock = () => { initNavigation: jest.fn(), setSideNavComponent: jest.fn(), setBreadcrumbs: jest.fn(), + getBreadcrumbs$: jest.fn(), getActiveNavigationNodes$: jest.fn(), getNavigationTreeUi$: jest.fn(), changeActiveSolutionNavigation: jest.fn(), From 72e2ca5df3a8bbb10964efa3157ed13c26dbc631 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loix?= Date: Tue, 15 Oct 2024 11:52:12 +0100 Subject: [PATCH 09/10] Fix TS issue --- x-pack/plugins/serverless/public/types.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/serverless/public/types.ts b/x-pack/plugins/serverless/public/types.ts index 7613cd50c0743..4627d24659b8e 100644 --- a/x-pack/plugins/serverless/public/types.ts +++ b/x-pack/plugins/serverless/public/types.ts @@ -6,7 +6,7 @@ */ import type { - ChromeProjectBreadcrumb, + ChromeBreadcrumb, ChromeSetProjectBreadcrumbsParams, SideNavComponent, NavigationTreeDefinition, @@ -21,7 +21,7 @@ export interface ServerlessPluginSetup {} export interface ServerlessPluginStart { setBreadcrumbs: ( - breadcrumbs: ChromeProjectBreadcrumb | ChromeProjectBreadcrumb[], + breadcrumbs: ChromeBreadcrumb | ChromeBreadcrumb[], params?: Partial ) => void; setProjectHome(homeHref: string): void; From bf3bd460533a4df3ae9418376809258554645fa8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loix?= Date: Tue, 15 Oct 2024 13:24:27 +0100 Subject: [PATCH 10/10] Fix functional tests --- .../functional_solution_sidenav/tests/observability_sidenav.ts | 2 +- x-pack/test/functional_solution_sidenav/tests/search_sidenav.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/test/functional_solution_sidenav/tests/observability_sidenav.ts b/x-pack/test/functional_solution_sidenav/tests/observability_sidenav.ts index f2712fd6cf5e7..b28469a935fe4 100644 --- a/x-pack/test/functional_solution_sidenav/tests/observability_sidenav.ts +++ b/x-pack/test/functional_solution_sidenav/tests/observability_sidenav.ts @@ -82,7 +82,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await solutionNavigation.sidenav.openSection('project_settings_project_nav'); await solutionNavigation.sidenav.clickLink({ deepLinkId: 'management' }); await solutionNavigation.sidenav.expectLinkActive({ deepLinkId: 'management' }); - await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ deepLinkId: 'management' }); + await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Stack Management' }); // navigate back to the home page using header logo await solutionNavigation.clickLogo(); diff --git a/x-pack/test/functional_solution_sidenav/tests/search_sidenav.ts b/x-pack/test/functional_solution_sidenav/tests/search_sidenav.ts index eb69631b09b0e..f90ea3e7b705f 100644 --- a/x-pack/test/functional_solution_sidenav/tests/search_sidenav.ts +++ b/x-pack/test/functional_solution_sidenav/tests/search_sidenav.ts @@ -64,7 +64,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await solutionNavigation.sidenav.openSection('project_settings_project_nav'); await solutionNavigation.sidenav.clickLink({ deepLinkId: 'management' }); await solutionNavigation.sidenav.expectLinkActive({ deepLinkId: 'management' }); - await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ deepLinkId: 'management' }); + await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Stack Management' }); // navigate back to the home page using header logo await solutionNavigation.clickLogo();