mirror of
https://github.com/elastic/kibana.git
synced 2025-06-27 18:51:07 -04:00
[Breadcrumbs] Hide "deployment" in breadcrumb when on-prem (#220110)
## Summary Closes #219869 **Before**  **After** <img width="1320" alt="image" src="https://github.com/user-attachments/assets/85ad1117-4aab-4a8d-807c-4fa90cd8b917" /> ### Checklist Check the PR satisfies following conditions. Reviewers should verify this PR satisfies this list as well. - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios
This commit is contained in:
parent
0712aa6ab8
commit
0acd88e3b9
5 changed files with 185 additions and 51 deletions
|
@ -462,6 +462,9 @@ describe('start', () => {
|
|||
it('allows the project breadcrumb to also be set', async () => {
|
||||
const { chrome } = await start();
|
||||
|
||||
chrome.project.setCloudUrls({
|
||||
deploymentUrl: 'my-deployment-url.com',
|
||||
});
|
||||
chrome.setBreadcrumbs([{ text: 'foo' }, { text: 'bar' }]); // only setting the classic breadcrumbs
|
||||
|
||||
{
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* 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", the "GNU Affero General Public License v3.0 only", and the "Server Side
|
||||
* Public License v 1"; you may not use this file except in compliance with, at
|
||||
* your election, the "Elastic License 2.0", the "GNU Affero General Public
|
||||
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||
*/
|
||||
|
||||
import type {
|
||||
ChromeBreadcrumb,
|
||||
ChromeProjectNavigationNode,
|
||||
CloudLinks,
|
||||
} from '@kbn/core-chrome-browser/src';
|
||||
import { buildBreadcrumbs } from './breadcrumbs';
|
||||
|
||||
describe('buildBreadcrumbs', () => {
|
||||
const mockCloudLinks = {
|
||||
deployment: { href: '/deployment' },
|
||||
deployments: { href: '/deployments', title: 'All Deployments' },
|
||||
} as CloudLinks;
|
||||
|
||||
it('returns breadcrumbs with root crumb when absolute is true', () => {
|
||||
const projectBreadcrumbs = {
|
||||
breadcrumbs: [{ text: 'Project Crumb', href: '/project' }],
|
||||
params: { absolute: true },
|
||||
};
|
||||
const result = buildBreadcrumbs({
|
||||
projectName: 'Test Project',
|
||||
cloudLinks: mockCloudLinks,
|
||||
projectBreadcrumbs,
|
||||
activeNodes: [],
|
||||
chromeBreadcrumbs: [],
|
||||
isServerless: true,
|
||||
});
|
||||
|
||||
expect(result).toEqual([
|
||||
expect.objectContaining({
|
||||
text: 'Test Project',
|
||||
}),
|
||||
...projectBreadcrumbs.breadcrumbs,
|
||||
]);
|
||||
});
|
||||
|
||||
it('builds breadcrumbs from activeNodes when no project breadcrumbs are set', () => {
|
||||
const activeNodes = [
|
||||
[
|
||||
{ title: 'Node 1', breadcrumbStatus: 'visible', href: '/node1' },
|
||||
{ title: 'Node 2', breadcrumbStatus: 'visible', href: '/node2' },
|
||||
],
|
||||
] as ChromeProjectNavigationNode[][];
|
||||
const result = buildBreadcrumbs({
|
||||
projectName: 'Test Project',
|
||||
cloudLinks: mockCloudLinks,
|
||||
projectBreadcrumbs: { breadcrumbs: [], params: { absolute: false } },
|
||||
activeNodes,
|
||||
chromeBreadcrumbs: [],
|
||||
isServerless: false,
|
||||
});
|
||||
|
||||
expect(result).toEqual([
|
||||
expect.objectContaining({
|
||||
text: 'Deployment',
|
||||
}),
|
||||
{ text: 'Node 1', href: '/node1' },
|
||||
{ text: 'Node 2', href: '/node2' },
|
||||
]);
|
||||
});
|
||||
|
||||
it('merges chromeBreadcrumbs and navBreadcrumbs based on deepLinkId', () => {
|
||||
const activeNodes = [
|
||||
[
|
||||
{ title: 'Node 1', breadcrumbStatus: 'visible', href: '/node1', deepLink: { id: '1' } },
|
||||
{ title: 'Node 2', breadcrumbStatus: 'visible', href: '/node2', deepLink: { id: '2' } },
|
||||
],
|
||||
] as ChromeProjectNavigationNode[][];
|
||||
const chromeBreadcrumbs = [
|
||||
{ text: 'Chrome Crumb 1', href: '/chrome1', deepLinkId: '2' },
|
||||
{ text: 'Chrome Crumb 2', href: '/chrome2' },
|
||||
] as ChromeBreadcrumb[];
|
||||
const result = buildBreadcrumbs({
|
||||
projectName: 'Test Project',
|
||||
cloudLinks: mockCloudLinks,
|
||||
projectBreadcrumbs: { breadcrumbs: [], params: { absolute: false } },
|
||||
activeNodes,
|
||||
chromeBreadcrumbs,
|
||||
isServerless: false,
|
||||
});
|
||||
|
||||
expect(result).toEqual([
|
||||
expect.objectContaining({
|
||||
text: 'Deployment',
|
||||
}),
|
||||
{ text: 'Node 1', href: '/node1', deepLinkId: '1' },
|
||||
{ text: 'Chrome Crumb 1', href: '/chrome1', deepLinkId: '2' },
|
||||
{ text: 'Chrome Crumb 2', href: '/chrome2' },
|
||||
]);
|
||||
});
|
||||
|
||||
it('returns breadcrumbs without root crumb if projectName/cloudLinks is empty', () => {
|
||||
const activeNodes = [
|
||||
[
|
||||
{ title: 'Node 1', breadcrumbStatus: 'visible', href: '/node1', deepLink: { id: '1' } },
|
||||
{ title: 'Node 2', breadcrumbStatus: 'visible', href: '/node2', deepLink: { id: '2' } },
|
||||
],
|
||||
] as ChromeProjectNavigationNode[][];
|
||||
const chromeBreadcrumbs = [
|
||||
{ text: 'Chrome Crumb 1', href: '/chrome1', deepLinkId: '2' },
|
||||
{ text: 'Chrome Crumb 2', href: '/chrome2' },
|
||||
] as ChromeBreadcrumb[];
|
||||
const result = buildBreadcrumbs({
|
||||
projectName: undefined,
|
||||
cloudLinks: {},
|
||||
projectBreadcrumbs: { breadcrumbs: [], params: { absolute: false } },
|
||||
activeNodes,
|
||||
chromeBreadcrumbs,
|
||||
isServerless: false,
|
||||
});
|
||||
|
||||
expect(result).toEqual([
|
||||
{ text: 'Node 1', href: '/node1', deepLinkId: '1' },
|
||||
{ text: 'Chrome Crumb 1', href: '/chrome1', deepLinkId: '2' },
|
||||
{ text: 'Chrome Crumb 2', href: '/chrome2' },
|
||||
]);
|
||||
});
|
||||
});
|
|
@ -19,6 +19,13 @@ import type {
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
|
||||
function prependRootCrumb(rootCrumb: ChromeBreadcrumb | undefined, rest: ChromeBreadcrumb[]) {
|
||||
if (rootCrumb) {
|
||||
return [rootCrumb, ...rest];
|
||||
}
|
||||
return rest;
|
||||
}
|
||||
|
||||
export function buildBreadcrumbs({
|
||||
projectName,
|
||||
cloudLinks,
|
||||
|
@ -44,7 +51,7 @@ export function buildBreadcrumbs({
|
|||
});
|
||||
|
||||
if (projectBreadcrumbs.params.absolute) {
|
||||
return [rootCrumb, ...projectBreadcrumbs.breadcrumbs];
|
||||
return prependRootCrumb(rootCrumb, projectBreadcrumbs.breadcrumbs);
|
||||
}
|
||||
|
||||
// breadcrumbs take the first active path
|
||||
|
@ -62,7 +69,7 @@ export function buildBreadcrumbs({
|
|||
|
||||
// if there are project breadcrumbs set, use them
|
||||
if (projectBreadcrumbs.breadcrumbs.length !== 0) {
|
||||
return [rootCrumb, ...navBreadcrumbs, ...projectBreadcrumbs.breadcrumbs];
|
||||
return prependRootCrumb(rootCrumb, [...navBreadcrumbs, ...projectBreadcrumbs.breadcrumbs]);
|
||||
}
|
||||
|
||||
// otherwise try to merge legacy breadcrumbs with navigational project breadcrumbs using deeplinkid
|
||||
|
@ -80,13 +87,12 @@ export function buildBreadcrumbs({
|
|||
}
|
||||
|
||||
if (chromeBreadcrumbStartIndex === -1) {
|
||||
return [rootCrumb, ...navBreadcrumbs];
|
||||
return prependRootCrumb(rootCrumb, navBreadcrumbs);
|
||||
} else {
|
||||
return [
|
||||
rootCrumb,
|
||||
return prependRootCrumb(rootCrumb, [
|
||||
...navBreadcrumbs.slice(0, navBreadcrumbEndIndex),
|
||||
...chromeBreadcrumbs.slice(chromeBreadcrumbStartIndex),
|
||||
];
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -98,7 +104,7 @@ function buildRootCrumb({
|
|||
projectName?: string;
|
||||
cloudLinks: CloudLinks;
|
||||
isServerless: boolean;
|
||||
}): ChromeBreadcrumb {
|
||||
}): ChromeBreadcrumb | undefined {
|
||||
if (isServerless) {
|
||||
return {
|
||||
text:
|
||||
|
@ -131,47 +137,49 @@ function buildRootCrumb({
|
|||
};
|
||||
}
|
||||
|
||||
return {
|
||||
text: i18n.translate('core.ui.primaryNav.cloud.deploymentLabel', {
|
||||
defaultMessage: 'Deployment',
|
||||
}),
|
||||
'data-test-subj': 'deploymentCrumb',
|
||||
popoverContent: () => (
|
||||
<>
|
||||
{cloudLinks.deployment && (
|
||||
<EuiButtonEmpty
|
||||
href={cloudLinks.deployment.href}
|
||||
color="text"
|
||||
iconType="gear"
|
||||
data-test-subj="manageDeploymentBtn"
|
||||
size="s"
|
||||
>
|
||||
{i18n.translate('core.ui.primaryNav.cloud.breadCrumbDropdown.manageDeploymentLabel', {
|
||||
defaultMessage: 'Manage this deployment',
|
||||
})}
|
||||
</EuiButtonEmpty>
|
||||
)}
|
||||
if (cloudLinks.deployment || cloudLinks.deployments) {
|
||||
return {
|
||||
text: i18n.translate('core.ui.primaryNav.cloud.deploymentLabel', {
|
||||
defaultMessage: 'Deployment',
|
||||
}),
|
||||
'data-test-subj': 'deploymentCrumb',
|
||||
popoverContent: () => (
|
||||
<>
|
||||
{cloudLinks.deployment && (
|
||||
<EuiButtonEmpty
|
||||
href={cloudLinks.deployment.href}
|
||||
color="text"
|
||||
iconType="gear"
|
||||
data-test-subj="manageDeploymentBtn"
|
||||
size="s"
|
||||
>
|
||||
{i18n.translate('core.ui.primaryNav.cloud.breadCrumbDropdown.manageDeploymentLabel', {
|
||||
defaultMessage: 'Manage this deployment',
|
||||
})}
|
||||
</EuiButtonEmpty>
|
||||
)}
|
||||
|
||||
{cloudLinks.deployments && (
|
||||
<EuiButtonEmpty
|
||||
href={cloudLinks.deployments.href}
|
||||
color="text"
|
||||
iconType="spaces"
|
||||
data-test-subj="viewDeploymentsBtn"
|
||||
size="s"
|
||||
>
|
||||
{cloudLinks.deployments.title}
|
||||
</EuiButtonEmpty>
|
||||
)}
|
||||
</>
|
||||
),
|
||||
popoverProps: {
|
||||
panelPaddingSize: 's',
|
||||
zIndex: 6000,
|
||||
panelStyle: { maxWidth: 240 },
|
||||
panelProps: {
|
||||
'data-test-subj': 'deploymentLinksPanel',
|
||||
{cloudLinks.deployments && (
|
||||
<EuiButtonEmpty
|
||||
href={cloudLinks.deployments.href}
|
||||
color="text"
|
||||
iconType="spaces"
|
||||
data-test-subj="viewDeploymentsBtn"
|
||||
size="s"
|
||||
>
|
||||
{cloudLinks.deployments.title}
|
||||
</EuiButtonEmpty>
|
||||
)}
|
||||
</>
|
||||
),
|
||||
popoverProps: {
|
||||
panelPaddingSize: 's',
|
||||
zIndex: 6000,
|
||||
panelStyle: { maxWidth: 240 },
|
||||
panelProps: {
|
||||
'data-test-subj': 'deploymentLinksPanel',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,7 +65,6 @@ export default function searchSolutionNavigation({
|
|||
await solutionNavigation.sidenav.expectLinkActive({
|
||||
deepLinkId: 'enterpriseSearch',
|
||||
});
|
||||
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Deployment' });
|
||||
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Data' });
|
||||
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Index Management' });
|
||||
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({
|
||||
|
@ -121,7 +120,6 @@ export default function searchSolutionNavigation({
|
|||
await solutionNavigation.sidenav.expectLinkActive({
|
||||
deepLinkId: 'elasticsearchIndexManagement',
|
||||
});
|
||||
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Deployment' });
|
||||
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Data' });
|
||||
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Index Management' });
|
||||
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({
|
||||
|
|
|
@ -52,7 +52,6 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
|||
await solutionNavigation.sidenav.expectLinkActive({
|
||||
deepLinkId: 'elasticsearchIndexManagement',
|
||||
});
|
||||
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Deployment' });
|
||||
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Data' });
|
||||
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Index Management' });
|
||||
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue