[Solution nav] Use flyout for Stack Management in Search and Observability solutions (#208632)

## Summary

Closes https://github.com/elastic/kibana/issues/208636
Part of https://github.com/elastic/kibana-team/issues/1439

### 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

### Identify risks

Does this PR introduce any risks? For example, consider risks like hard
to test bugs, performance regression, potential of data loss.

Describe the risk, its severity, and mitigation for each identified
risk. Invite stakeholders and evaluate how to proceed before merging.

- [ ] New lists of Stack Management navigation items were added for
flyout menus in serverless projects using static declarations. There is
a risk that these lists have missing items, which could hurt user
experience by making the pages harder to navigate to.

### Screenshots
<details><summary>Observability / Serverless</summary>

![optimized-serverless-observability 4 48
01 PM](https://github.com/user-attachments/assets/03d40840-385c-4a89-a181-a9b5ba82f820)

</details>
<details><summary>Observability / Stateful</summary>

![optimized-stateful-observability 4 48
01 PM](https://github.com/user-attachments/assets/e267e87a-584c-406d-8fea-99788fb2c0dd)

</details>
<details><summary>Search / Serverless</summary>

![optimized-serverless-search 4 48
01 PM](https://github.com/user-attachments/assets/258da8ec-5144-4439-b29f-b894b28963ad)

</details>
<details><summary>Search / Stateful</summary>

![optimized-stateful-search 4 48
01 PM](https://github.com/user-attachments/assets/fd6db7bb-536b-4804-950b-00f6716663ac)
This commit is contained in:
Tim Sullivan 2025-02-11 09:14:32 -07:00 committed by GitHub
parent 2e29a504a7
commit f16446486c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 167 additions and 29 deletions

View file

@ -36,6 +36,7 @@ export type ManagementId =
| 'cross_cluster_replication'
| 'dataViews'
| 'data_quality'
| 'data_usage'
| 'filesManagement'
| 'license_management'
| 'index_lifecycle_management'

View file

@ -439,7 +439,6 @@ function createNavTree({ streamsAvailable }: { streamsAvailable?: boolean }) {
children: [
{
id: 'stack_management', // This id can't be changed as we use it to open the panel programmatically
link: 'management',
title: i18n.translate('xpack.observability.obltNav.stackManagement', {
defaultMessage: 'Stack Management',
}),

View file

@ -355,10 +355,73 @@ export const createNavigationTree = ({
breadcrumbStatus: 'hidden',
children: [
{
link: 'management',
id: 'management',
title: i18n.translate('xpack.serverlessObservability.nav.mngt', {
defaultMessage: 'Management',
}),
spaceBefore: null,
renderAs: 'panelOpener',
children: [
{
title: i18n.translate('xpack.serverlessObservability.nav.mngt.data', {
defaultMessage: 'Data',
}),
breadcrumbStatus: 'hidden',
children: [
{ link: 'management:index_management', breadcrumbStatus: 'hidden' },
{ link: 'management:transform', breadcrumbStatus: 'hidden' },
{ link: 'management:ingest_pipelines', breadcrumbStatus: 'hidden' },
{ link: 'management:dataViews', breadcrumbStatus: 'hidden' },
{ link: 'management:jobsListLink', breadcrumbStatus: 'hidden' },
{ link: 'management:pipelines', breadcrumbStatus: 'hidden' },
{ link: 'management:data_quality', breadcrumbStatus: 'hidden' },
{ link: 'management:data_usage', breadcrumbStatus: 'hidden' },
],
},
{
title: i18n.translate('xpack.serverlessObservability.nav.mngt.access', {
defaultMessage: 'Access',
}),
breadcrumbStatus: 'hidden',
children: [{ link: 'management:api_keys', breadcrumbStatus: 'hidden' }],
},
{
title: i18n.translate('xpack.serverlessObservability.nav.mngt.alertsAndInsights', {
defaultMessage: 'Alerts and insights',
}),
breadcrumbStatus: 'hidden',
children: [
{ link: 'management:triggersActionsConnectors', breadcrumbStatus: 'hidden' },
{ link: 'management:maintenanceWindows', breadcrumbStatus: 'hidden' },
],
},
{
title: i18n.translate('xpack.serverlessObservability.nav.mngt.content', {
defaultMessage: 'Content',
}),
breadcrumbStatus: 'hidden',
children: [
{ link: 'management:spaces', breadcrumbStatus: 'hidden' },
{ link: 'management:objects', breadcrumbStatus: 'hidden' },
{ link: 'management:filesManagement', breadcrumbStatus: 'hidden' },
{ link: 'management:reporting', breadcrumbStatus: 'hidden' },
{ link: 'management:tags', breadcrumbStatus: 'hidden' },
],
},
{
title: i18n.translate('xpack.serverlessObservability.nav.mngt.other', {
defaultMessage: 'Other',
}),
breadcrumbStatus: 'hidden',
children: [
{ link: 'management:settings', breadcrumbStatus: 'hidden' },
{
link: 'management:observabilityAiAssistantManagement',
breadcrumbStatus: 'hidden',
},
],
},
],
},
{
link: 'integrations',

View file

@ -306,7 +306,6 @@ export const getNavigationTreeDefinition = ({
},
],
id: 'stack_management', // This id can't be changed as we use it to open the panel programmatically
link: 'management',
renderAs: 'panelOpener',
spaceBefore: null,
title: i18n.translate('xpack.enterpriseSearch.searchNav.mngt', {

View file

@ -167,10 +167,86 @@ export const navigationTree = ({ isAppRegistered }: ApplicationStart): Navigatio
}),
},
{
link: 'management',
id: 'management',
title: i18n.translate('xpack.serverlessSearch.nav.mngt', {
defaultMessage: 'Management',
}),
spaceBefore: null,
renderAs: 'panelOpener',
children: [
{
title: i18n.translate('xpack.serverlessSearch.nav.mngt.data', {
defaultMessage: 'Data',
}),
breadcrumbStatus: 'hidden',
children: [
{ link: 'management:index_management', breadcrumbStatus: 'hidden' },
{ link: 'management:transform', breadcrumbStatus: 'hidden' },
{ link: 'management:ingest_pipelines', breadcrumbStatus: 'hidden' },
{ link: 'management:dataViews', breadcrumbStatus: 'hidden' },
{ link: 'management:jobsListLink', breadcrumbStatus: 'hidden' },
{ link: 'management:pipelines', breadcrumbStatus: 'hidden' },
{ link: 'management:data_quality', breadcrumbStatus: 'hidden' },
{ link: 'management:data_usage', breadcrumbStatus: 'hidden' },
],
},
{
title: i18n.translate('xpack.serverlessSearch.nav.mngt.access', {
defaultMessage: 'Access',
}),
breadcrumbStatus: 'hidden',
children: [
{ link: 'management:api_keys', breadcrumbStatus: 'hidden' },
{ link: 'management:roles', breadcrumbStatus: 'hidden' },
{
cloudLink: 'userAndRoles',
title: i18n.translate('xpack.serverlessSearch.nav.mngt.access.userAndRoles', {
defaultMessage: 'Manage Organization Members',
}),
},
],
},
{
title: i18n.translate('xpack.serverlessSearch.nav.mngt.alertsAndInsights', {
defaultMessage: 'Alerts and insights',
}),
breadcrumbStatus: 'hidden',
children: [
{ link: 'management:triggersActions', breadcrumbStatus: 'hidden' },
{ link: 'management:triggersActionsConnectors', breadcrumbStatus: 'hidden' },
],
},
{
title: i18n.translate('xpack.serverlessSearch.nav.mngt.content', {
defaultMessage: 'Content',
}),
breadcrumbStatus: 'hidden',
children: [
{ link: 'management:spaces', breadcrumbStatus: 'hidden' },
{ link: 'management:objects', breadcrumbStatus: 'hidden' },
{ link: 'management:filesManagement', breadcrumbStatus: 'hidden' },
{ link: 'management:reporting', breadcrumbStatus: 'hidden' },
{ link: 'management:tags', breadcrumbStatus: 'hidden' },
],
},
{
title: i18n.translate('xpack.serverlessSearch.nav.mngt.other', {
defaultMessage: 'Other',
}),
breadcrumbStatus: 'hidden',
children: [
{ link: 'management:settings', breadcrumbStatus: 'hidden' },
{
link: 'management:observabilityAiAssistantManagement',
breadcrumbStatus: 'hidden',
title: i18n.translate(
'xpack.serverlessSearch.nav.mngt.other.aiAssistantSettings',
{ defaultMessage: 'AI Assistant Settings' }
),
},
],
},
],
},
{
id: 'cloudLinkDeployment',

View file

@ -80,8 +80,9 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
// navigate to a different section
await solutionNavigation.sidenav.openSection('project_settings_project_nav');
await solutionNavigation.sidenav.clickLink({ deepLinkId: 'management' });
await solutionNavigation.sidenav.expectLinkActive({ deepLinkId: 'management' });
await solutionNavigation.sidenav.clickLink({ navId: 'stack_management' });
await solutionNavigation.sidenav.expectLinkActive({ navId: 'stack_management' });
await solutionNavigation.sidenav.clickPanelLink('management:tags');
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Stack Management' });
// navigate back to the home page using header logo

View file

@ -64,8 +64,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
// navigate to a different section
await solutionNavigation.sidenav.openSection('project_settings_project_nav');
await solutionNavigation.sidenav.clickLink({ deepLinkId: 'management' });
await solutionNavigation.sidenav.expectLinkActive({ deepLinkId: 'management' });
await solutionNavigation.sidenav.clickLink({ navId: 'stack_management' });
await solutionNavigation.sidenav.expectLinkActive({ navId: 'stack_management' });
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Stack Management' });
// navigate back to the home page using header logo

View file

@ -49,9 +49,10 @@ export default function ({ getPageObject, getService }: FtrProviderContext) {
await svlCommonNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'AI Assistant' });
// navigate to a different section
await svlCommonNavigation.sidenav.openSection('project_settings_project_nav');
await svlCommonNavigation.sidenav.clickLink({ deepLinkId: 'management' });
await svlCommonNavigation.sidenav.expectLinkActive({ deepLinkId: 'management' });
await svlCommonNavigation.breadcrumbs.expectBreadcrumbExists({ deepLinkId: 'management' });
await svlCommonNavigation.sidenav.clickLink({ navId: 'management' });
await svlCommonNavigation.sidenav.expectLinkActive({ navId: 'management' });
await svlCommonNavigation.sidenav.clickPanelLink('management:tags');
await svlCommonNavigation.breadcrumbs.expectBreadcrumbTexts(['Management', 'Tags']);
// navigate back to serverless oblt overview
await svlCommonNavigation.clickLogo();
@ -65,7 +66,8 @@ export default function ({ getPageObject, getService }: FtrProviderContext) {
it('active sidenav section is auto opened on load', async () => {
await svlCommonNavigation.sidenav.openSection('project_settings_project_nav');
await svlCommonNavigation.sidenav.clickLink({ deepLinkId: 'management' });
await svlCommonNavigation.sidenav.clickLink({ navId: 'management' });
await svlCommonNavigation.sidenav.clickPanelLink('management:tags');
await browser.refresh();
await svlCommonNavigation.expectExists();
await svlCommonNavigation.sidenav.expectSectionOpen('project_settings_project_nav');
@ -134,8 +136,8 @@ export default function ({ getPageObject, getService }: FtrProviderContext) {
it('navigates to maintenance windows', async () => {
await svlCommonNavigation.sidenav.openSection('project_settings_project_nav');
await svlCommonNavigation.sidenav.clickLink({ deepLinkId: 'management' });
await testSubjects.click('app-card-maintenanceWindows');
await svlCommonNavigation.sidenav.clickLink({ navId: 'management' });
await svlCommonNavigation.sidenav.clickPanelLink('management:maintenanceWindows');
await svlCommonNavigation.breadcrumbs.expectBreadcrumbTexts([
'Management',
'Maintenance Windows',

View file

@ -164,16 +164,10 @@ export default function ({ getPageObject, getService }: FtrProviderContext) {
deepLinkId: 'ml:modelManagement',
});
// > Management
await solutionNavigation.sidenav.clickLink({
deepLinkId: 'management',
});
await solutionNavigation.sidenav.expectLinkActive({
deepLinkId: 'management',
});
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Management' });
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({
deepLinkId: 'management',
});
await solutionNavigation.sidenav.clickLink({ navId: 'management' });
await solutionNavigation.sidenav.expectLinkActive({ navId: 'management' });
await svlCommonNavigation.sidenav.clickPanelLink('management:tags');
await svlCommonNavigation.breadcrumbs.expectBreadcrumbTexts(['Management', 'Tags']);
// navigate back to serverless search overview
await svlCommonNavigation.clickLogo();
@ -206,9 +200,12 @@ export default function ({ getPageObject, getService }: FtrProviderContext) {
it('navigate management', async () => {
await svlCommonNavigation.sidenav.openSection('project_settings_project_nav');
await svlCommonNavigation.sidenav.clickLink({ deepLinkId: 'management' });
await svlCommonNavigation.breadcrumbs.expectBreadcrumbTexts(['Management']);
await testSubjects.click('app-card-dataViews');
await svlCommonNavigation.sidenav.clickLink({ navId: 'management' });
await svlCommonNavigation.sidenav.clickPanelLink('management:tags');
await svlCommonNavigation.breadcrumbs.expectBreadcrumbTexts(['Management', 'Tags']);
await svlCommonNavigation.sidenav.clickLink({ navId: 'management' });
await svlCommonNavigation.sidenav.clickPanelLink('management:dataViews');
await svlCommonNavigation.breadcrumbs.expectBreadcrumbTexts(['Management', 'Data views']);
});

View file

@ -20,8 +20,8 @@ export default function ({ getPageObjects }: FtrProviderContext) {
before(async () => {
await pageObjects.svlCommonPage.loginWithRole('developer');
await pageObjects.svlCommonNavigation.sidenav.openSection('project_settings_project_nav');
await pageObjects.svlCommonNavigation.sidenav.clickLink({ deepLinkId: 'management' });
await pageObjects.svlManagementPage.clickIngestPipelinesManagementCard();
await pageObjects.svlCommonNavigation.sidenav.clickLink({ navId: 'management' });
await pageObjects.svlCommonNavigation.sidenav.clickPanelLink('management:ingest_pipelines');
});
it('has embedded console', async () => {