From 47bc2c9e28d977f651dad3205c6de9d7693c6234 Mon Sep 17 00:00:00 2001 From: Sergi Massaneda Date: Tue, 23 Jan 2024 11:04:41 +0100 Subject: [PATCH] [Security Solution] Cleanup legacy serverless navigation (#175214) ## Summary https://github.com/elastic/kibana/issues/174944 Remove the legacy navigation components, chrome navigation tree, and experimental feature. This PR only removes unused code, It does not introduce any behavioral change. The project navigation is already enabled. --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../common/experimental_features.ts | 7 +- .../public/navigation/index.ts | 17 +- .../chrome_navigation_tree.test.ts | 245 ------------------ .../navigation_tree/chrome_navigation_tree.ts | 103 -------- .../navigation/navigation_tree/index.ts | 32 --- .../navigation/project_navigation/index.tsx | 15 -- .../__mocks__/use_side_nav_items.ts | 21 -- .../navigation/side_navigation/index.tsx | 13 +- .../navigation/side_navigation/lazy.tsx | 17 -- .../navigation_tree.test.ts | 0 .../navigation_tree.ts | 0 .../project_navigation.tsx | 6 +- .../side_navigation/side_navigation.test.tsx | 183 ------------- .../side_navigation/side_navigation.tsx | 116 --------- .../side_navigation_footer.test.tsx | 153 ----------- .../side_navigation_footer.tsx | 135 ---------- ....tsx => use_panel_side_nav_items.test.tsx} | 74 +++--- ...v_items.ts => use_panel_side_nav_items.ts} | 15 +- .../utils.ts | 0 .../tsconfig.json | 2 - 20 files changed, 56 insertions(+), 1098 deletions(-) delete mode 100644 x-pack/plugins/security_solution_serverless/public/navigation/navigation_tree/chrome_navigation_tree.test.ts delete mode 100644 x-pack/plugins/security_solution_serverless/public/navigation/navigation_tree/chrome_navigation_tree.ts delete mode 100644 x-pack/plugins/security_solution_serverless/public/navigation/navigation_tree/index.ts delete mode 100644 x-pack/plugins/security_solution_serverless/public/navigation/project_navigation/index.tsx delete mode 100644 x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/__mocks__/use_side_nav_items.ts delete mode 100644 x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/lazy.tsx rename x-pack/plugins/security_solution_serverless/public/navigation/{navigation_tree => side_navigation}/navigation_tree.test.ts (100%) rename x-pack/plugins/security_solution_serverless/public/navigation/{navigation_tree => side_navigation}/navigation_tree.ts (100%) rename x-pack/plugins/security_solution_serverless/public/navigation/{project_navigation => side_navigation}/project_navigation.tsx (91%) delete mode 100644 x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/side_navigation.test.tsx delete mode 100644 x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/side_navigation.tsx delete mode 100644 x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/side_navigation_footer.test.tsx delete mode 100644 x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/side_navigation_footer.tsx rename x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/{use_side_nav_items.test.tsx => use_panel_side_nav_items.test.tsx} (64%) rename x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/{use_side_nav_items.ts => use_panel_side_nav_items.ts} (83%) rename x-pack/plugins/security_solution_serverless/public/navigation/{navigation_tree => side_navigation}/utils.ts (100%) diff --git a/x-pack/plugins/security_solution_serverless/common/experimental_features.ts b/x-pack/plugins/security_solution_serverless/common/experimental_features.ts index 76b57064da160..da5026c3f322a 100644 --- a/x-pack/plugins/security_solution_serverless/common/experimental_features.ts +++ b/x-pack/plugins/security_solution_serverless/common/experimental_features.ts @@ -17,9 +17,12 @@ export type ServerlessExperimentalFeatures = Record< */ export const allowedExperimentalValues = Object.freeze({ /** - * Enables the use of the of the product navigation from shared-ux package in the Security Solution app + * + * + * [This is a fake feature key to showcase how to add a new serverless-specific experimental flag. + * It also prevents `allowedExperimentalValues` from being empty. It should be removed once a real feature is added.] */ - platformNavEnabled: true, + _serverlessFeatureEnabled: false, }); type ServerlessExperimentalConfigKeys = Array; diff --git a/x-pack/plugins/security_solution_serverless/public/navigation/index.ts b/x-pack/plugins/security_solution_serverless/public/navigation/index.ts index 0da5ccf9db3c8..5e4907501a995 100644 --- a/x-pack/plugins/security_solution_serverless/public/navigation/index.ts +++ b/x-pack/plugins/security_solution_serverless/public/navigation/index.ts @@ -10,8 +10,7 @@ import type { CoreSetup } from '@kbn/core/public'; import type { SecuritySolutionServerlessPluginSetupDeps } from '../types'; import type { Services } from '../common/services'; import { subscribeBreadcrumbs } from './breadcrumbs'; -import { getSecuritySideNavComponent } from './side_navigation'; -import { initProjectNavigation } from './project_navigation'; +import { initSideNavigation } from './side_navigation'; import { projectAppLinksSwitcher } from './links/app_links'; import { formatProjectDeepLinks } from './links/deep_links'; import { enableManagementCardsLanding } from './management_cards'; @@ -27,21 +26,9 @@ export const setupNavigation = ( export const startNavigation = (services: Services) => { const { serverless, management } = services; serverless.setProjectHome(APP_PATH); + initSideNavigation(services); enableManagementCardsLanding(services); - - if (services.experimentalFeatures.platformNavEnabled) { - initProjectNavigation(services); - } else { - // TODO: Remove this else block as platform is enabled by default - // Issue: https://github.com/elastic/kibana/issues/174944 - - // const projectNavigationTree = new ProjectNavigationTree(services); - // projectNavigationTree.getChromeNavigationTree$().subscribe((chromeNavigationTree) => { - // serverless.setNavigation({ navigationTree: chromeNavigationTree }); - // }); - serverless.setSideNavComponentDeprecated(getSecuritySideNavComponent(services)); - } management.setIsSidebarEnabled(false); subscribeBreadcrumbs(services); diff --git a/x-pack/plugins/security_solution_serverless/public/navigation/navigation_tree/chrome_navigation_tree.test.ts b/x-pack/plugins/security_solution_serverless/public/navigation/navigation_tree/chrome_navigation_tree.test.ts deleted file mode 100644 index 74979b0549b91..0000000000000 --- a/x-pack/plugins/security_solution_serverless/public/navigation/navigation_tree/chrome_navigation_tree.test.ts +++ /dev/null @@ -1,245 +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 type { ChromeNavLink } from '@kbn/core/public'; -import { APP_UI_ID } from '@kbn/security-solution-plugin/common'; -import { SecurityPageName } from '@kbn/security-solution-navigation'; -import { getFormatChromeProjectNavNodes } from './chrome_navigation_tree'; -import { mockServices } from '../../common/services/__mocks__/services.mock'; -import type { ProjectNavigationLink } from '../links/types'; -import type { ExternalPageName } from '../links/constants'; -import * as ml from '@kbn/default-nav-ml'; - -jest.mock('@kbn/default-nav-ml'); - -const link1Id = 'link-1' as SecurityPageName; -const link2Id = 'link-2' as SecurityPageName; -const link3Id = 'externalAppId:link-1' as ExternalPageName; - -const link1: ProjectNavigationLink = { id: link1Id, title: 'link 1' }; -const link2: ProjectNavigationLink = { id: link2Id, title: 'link 2' }; -const link3: ProjectNavigationLink = { id: link3Id, title: 'link 3' }; - -const chromeNavLink1: ChromeNavLink = { - id: `${APP_UI_ID}:${link1.id}`, - title: link1.title, - href: '/link1', - url: '/link1', - baseUrl: '', -}; -const chromeNavLink2: ChromeNavLink = { - id: `${APP_UI_ID}:${link2.id}`, - title: link2.title, - href: '/link2', - url: '/link2', - baseUrl: '', -}; -const chromeNavLink3: ChromeNavLink = { - id: link3.id, - title: link3.title, - href: '/link3', - url: '/link3', - baseUrl: '', -}; -const chromeNavLinkMl1: ChromeNavLink = { - id: 'ml:subLink-1', - title: 'ML subLink 1', - href: '/ml/link1', - url: '/ml/link1', - baseUrl: '', -}; -const chromeNavLinkMl2: ChromeNavLink = { - id: 'ml:subLink-2', - title: 'ML subLink 2', - href: '/ml/link2', - url: '/ml/link2', - baseUrl: '', -}; -const defaultNavCategory1 = { - id: 'category_one', - title: 'ML Category1', -}; - -(ml as { defaultNavigation: unknown }).defaultNavigation = { - children: [ - { - id: 'root', - children: [ - { - link: chromeNavLinkMl1.id, - }, - ], - }, - { - ...defaultNavCategory1, - children: [ - { - title: 'Overridden ML SubLink 2', - link: chromeNavLinkMl2.id, - }, - ], - }, - ], -}; - -let chromeNavLinks: ChromeNavLink[] = []; -const mockChromeNavLinksGet = jest.fn((id: string): ChromeNavLink | undefined => - chromeNavLinks.find((link) => link.id === id) -); -const mockChromeNavLinksHas = jest.fn((id: string): boolean => - chromeNavLinks.some((link) => link.id === id) -); - -const testServices = { - ...mockServices, - chrome: { - ...mockServices.chrome, - navLinks: { - ...mockServices.chrome.navLinks, - get: mockChromeNavLinksGet, - has: mockChromeNavLinksHas, - }, - }, -}; - -describe('formatChromeProjectNavNodes', () => { - const formatChromeProjectNavNodes = getFormatChromeProjectNavNodes(testServices); - - beforeEach(() => { - jest.clearAllMocks(); - chromeNavLinks = [chromeNavLink1, chromeNavLink2, chromeNavLink3]; - }); - - it('should format regular chrome nav nodes', async () => { - const chromeNavNodes = formatChromeProjectNavNodes([link1]); - expect(chromeNavNodes).toEqual([ - { - id: chromeNavLink1.id, - title: link1.title, - path: chromeNavLink1.id, - deepLink: chromeNavLink1, - }, - ]); - }); - - it('should format external chrome nav nodes', async () => { - const chromeNavNodes = formatChromeProjectNavNodes([link3]); - - expect(chromeNavNodes).toEqual([ - { - id: chromeNavLink3.id, - title: chromeNavLink3.title, - path: chromeNavLink3.id, - deepLink: chromeNavLink3, - }, - ]); - }); - - it('should format nested links to chrome nav nodes', async () => { - const chromeNavNodes = formatChromeProjectNavNodes([{ ...link1, links: [link2] }]); - - expect(chromeNavNodes).toEqual([ - { - id: chromeNavLink1.id, - title: link1.title, - path: chromeNavLink1.id, - deepLink: chromeNavLink1, - children: [ - { - id: chromeNavLink2.id, - title: link2.title, - path: [chromeNavLink1.id, chromeNavLink2.id].join('.'), - deepLink: chromeNavLink2, - }, - ], - }, - ]); - }); - - it('should use the preset nav for ML lings', async () => { - const chromeNavLinkTest = { - ...chromeNavLink1, - id: `${APP_UI_ID}:${SecurityPageName.mlLanding}`, - }; - chromeNavLinks = [chromeNavLinkTest, chromeNavLinkMl1, chromeNavLinkMl2]; - const chromeNavNodes = formatChromeProjectNavNodes([ - { ...link1, id: SecurityPageName.mlLanding }, - ]); - - expect(chromeNavNodes).toEqual([ - { - id: chromeNavLinkTest.id, - title: link1.title, - path: chromeNavLinkTest.id, - deepLink: chromeNavLinkTest, - children: [ - { - id: chromeNavLinkMl1.id, - title: chromeNavLinkMl1.title, - path: [chromeNavLinkTest.id, chromeNavLinkMl1.id].join('.'), - deepLink: chromeNavLinkMl1, - }, - { - id: defaultNavCategory1.id, - title: defaultNavCategory1.title, - path: [chromeNavLinkTest.id, defaultNavCategory1.id].join('.'), - children: [ - { - id: chromeNavLinkMl2.id, - title: 'Overridden ML SubLink 2', - path: [chromeNavLinkTest.id, defaultNavCategory1.id, chromeNavLinkMl2.id].join('.'), - deepLink: chromeNavLinkMl2, - }, - ], - }, - ], - }, - ]); - }); - - it('should not include links that are not in the chrome navLinks', async () => { - chromeNavLinks = [chromeNavLink2]; - const chromeNavNodes = formatChromeProjectNavNodes([link1, link2]); - - expect(chromeNavNodes).toEqual([ - { - id: chromeNavLink2.id, - title: link2.title, - path: chromeNavLink2.id, - deepLink: chromeNavLink2, - }, - ]); - }); - - it('should set hidden breadcrumb for blacklisted links', async () => { - const chromeNavLinkTest = { - ...chromeNavLink1, - id: `${APP_UI_ID}:${SecurityPageName.usersEvents}`, // userEvents link is blacklisted - }; - chromeNavLinks = [chromeNavLinkTest, chromeNavLink2]; - - const chromeNavNodes = formatChromeProjectNavNodes([ - { ...link1, id: SecurityPageName.usersEvents }, - link2, - ]); - - expect(chromeNavNodes).toEqual([ - { - id: chromeNavLinkTest.id, - title: link1.title, - path: chromeNavLinkTest.id, - deepLink: chromeNavLinkTest, - breadcrumbStatus: 'hidden', - }, - { - id: chromeNavLink2.id, - title: link2.title, - path: chromeNavLink2.id, - deepLink: chromeNavLink2, - }, - ]); - }); -}); diff --git a/x-pack/plugins/security_solution_serverless/public/navigation/navigation_tree/chrome_navigation_tree.ts b/x-pack/plugins/security_solution_serverless/public/navigation/navigation_tree/chrome_navigation_tree.ts deleted file mode 100644 index b787aeb927361..0000000000000 --- a/x-pack/plugins/security_solution_serverless/public/navigation/navigation_tree/chrome_navigation_tree.ts +++ /dev/null @@ -1,103 +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 type { ChromeProjectNavigationNode, NodeDefinition } from '@kbn/core-chrome-browser'; -import { defaultNavigation as mlDefaultNav } from '@kbn/default-nav-ml'; -import { defaultNavigation as devToolsDefaultNav } from '@kbn/default-nav-devtools'; -import { SecurityPageName } from '@kbn/security-solution-navigation'; -import type { Services } from '../../common/services'; -import type { ProjectNavigationLink, ProjectPageName } from '../links/types'; -import { getNavLinkIdFromProjectPageName } from '../links/util'; -import { ExternalPageName } from '../links/constants'; -import { isBreadcrumbHidden } from './utils'; - -// Closure to access the "up-to-date" chrome.navLinks from services -export const getFormatChromeProjectNavNodes = (services: Services) => { - const formatChromeProjectNavNodes = ( - projectNavLinks: ProjectNavigationLink[], - path?: string - ): ChromeProjectNavigationNode[] => { - const { chrome } = services; - - return projectNavLinks.reduce((navNodes, navLink) => { - const { id, title, links } = navLink; - const navLinkId = getNavLinkIdFromProjectPageName(id); - - if (chrome.navLinks.has(navLinkId)) { - const link: ChromeProjectNavigationNode = { - id: navLinkId, - title, - path: path ? [path, navLinkId].join('.') : navLinkId, - deepLink: chrome.navLinks.get(navLinkId), - ...(isBreadcrumbHidden(id) && { breadcrumbStatus: 'hidden' }), - }; - // check default navigation for children - const defaultChildrenNav = getDefaultChildrenNav(id, link); - if (defaultChildrenNav) { - link.children = defaultChildrenNav; - } else if (links?.length) { - link.children = formatChromeProjectNavNodes(links, link.path); - } - navNodes.push(link); - } - return navNodes; - }, []); - }; - - const getDefaultChildrenNav = ( - id: ProjectPageName, - link: ChromeProjectNavigationNode - ): ChromeProjectNavigationNode[] | undefined => { - if (id === SecurityPageName.mlLanding) { - return processDefaultNav(mlDefaultNav.children, link.path); - } - if (id === ExternalPageName.devTools) { - return processDefaultNav(devToolsDefaultNav.children, link.path); - } - return undefined; - }; - - const processDefaultNav = ( - children: NodeDefinition[], - path: string - ): ChromeProjectNavigationNode[] => { - const { chrome } = services; - return children.reduce((navNodes, node) => { - const id = node.id ?? node.link; - if (!id) { - return navNodes; - } - if (id === 'root') { - if (node.children) { - navNodes.push(...processDefaultNav(node.children, path)); - } - return navNodes; - } - const navNode: ChromeProjectNavigationNode = { - id, - title: node.title || '', - path: [path, id].join('.'), - breadcrumbStatus: node.breadcrumbStatus, - getIsActive: node.getIsActive, - }; - if (chrome.navLinks.has(id)) { - const deepLink = chrome.navLinks.get(id); - navNode.deepLink = deepLink; - if (!navNode.title) { - navNode.title = deepLink?.title || ''; - } - } - if (node.children?.length) { - navNode.children = processDefaultNav(node.children, navNode.path); - } - navNodes.push(navNode); - return navNodes; - }, []); - }; - - return formatChromeProjectNavNodes; -}; diff --git a/x-pack/plugins/security_solution_serverless/public/navigation/navigation_tree/index.ts b/x-pack/plugins/security_solution_serverless/public/navigation/navigation_tree/index.ts deleted file mode 100644 index a1a04b9ca236e..0000000000000 --- a/x-pack/plugins/security_solution_serverless/public/navigation/navigation_tree/index.ts +++ /dev/null @@ -1,32 +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 type { Observable } from 'rxjs'; -import { map } from 'rxjs'; -import type { ChromeProjectNavigationNode } from '@kbn/core-chrome-browser'; -import type { Services } from '../../common/services'; -import type { ProjectNavLinks } from '../links/types'; -import { getFormatChromeProjectNavNodes } from './chrome_navigation_tree'; - -/** - * This class is temporary until we can remove the chrome navigation tree and use only the formatNavigationTree - */ -export class ProjectNavigationTree { - private projectNavLinks$: ProjectNavLinks; - - constructor(private readonly services: Services) { - const { getProjectNavLinks$ } = this.services; - this.projectNavLinks$ = getProjectNavLinks$(); - } - - public getChromeNavigationTree$(): Observable { - const formatChromeProjectNavNodes = getFormatChromeProjectNavNodes(this.services); - return this.projectNavLinks$.pipe( - map((projectNavLinks) => formatChromeProjectNavNodes(projectNavLinks)) - ); - } -} diff --git a/x-pack/plugins/security_solution_serverless/public/navigation/project_navigation/index.tsx b/x-pack/plugins/security_solution_serverless/public/navigation/project_navigation/index.tsx deleted file mode 100644 index 99b93af899789..0000000000000 --- a/x-pack/plugins/security_solution_serverless/public/navigation/project_navigation/index.tsx +++ /dev/null @@ -1,15 +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 { type Services } from '../../common/services'; - -export const initProjectNavigation = (services: Services) => { - import('./project_navigation').then(({ init }) => { - const { navigationTree$, panelContentProvider, dataTestSubj } = init(services); - services.serverless.initNavigation(navigationTree$, { panelContentProvider, dataTestSubj }); - }); -}; diff --git a/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/__mocks__/use_side_nav_items.ts b/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/__mocks__/use_side_nav_items.ts deleted file mode 100644 index a01612190d8f9..0000000000000 --- a/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/__mocks__/use_side_nav_items.ts +++ /dev/null @@ -1,21 +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 type { SolutionSideNavItem } from '@kbn/security-solution-side-nav'; - -const { usePartitionFooterNavItems: originalUsePartitionFooterNavItems } = - jest.requireActual('../use_side_nav_items'); - -export const useSideNavItems = jest.fn((): SolutionSideNavItem[] => []); - -export const usePartitionFooterNavItems = jest.fn( - (sideNavItems: SolutionSideNavItem[]): [SolutionSideNavItem[], SolutionSideNavItem[]] => - // Same implementation as original for convenience. Can be overridden in tests if needed - originalUsePartitionFooterNavItems(sideNavItems) -); - -export const useSideNavSelectedId = jest.fn((_sideNavItems: SolutionSideNavItem[]): string => ''); diff --git a/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/index.tsx b/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/index.tsx index 6ee90bc3a5164..1e2d3a45827b2 100644 --- a/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/index.tsx +++ b/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/index.tsx @@ -4,11 +4,12 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import React from 'react'; -import type { SideNavComponent } from '@kbn/core-chrome-browser'; -import { SecuritySideNavigation } from './lazy'; -import { withServicesProvider, type Services } from '../../common/services'; +import { type Services } from '../../common/services'; -export const getSecuritySideNavComponent = (services: Services): SideNavComponent => - React.memo(withServicesProvider(SecuritySideNavigation, services)); +export const initSideNavigation = (services: Services) => { + import('./project_navigation').then(({ init }) => { + const { navigationTree$, panelContentProvider, dataTestSubj } = init(services); + services.serverless.initNavigation(navigationTree$, { panelContentProvider, dataTestSubj }); + }); +}; diff --git a/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/lazy.tsx b/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/lazy.tsx deleted file mode 100644 index 33af766372dec..0000000000000 --- a/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/lazy.tsx +++ /dev/null @@ -1,17 +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 React, { lazy, Suspense } from 'react'; -import { EuiLoadingSpinner } from '@elastic/eui'; -import type { SideNavComponent } from '@kbn/core-chrome-browser'; - -const SecuritySideNavigationLazy = lazy(() => import('./side_navigation')); - -export const SecuritySideNavigation: SideNavComponent = (props) => ( - }> - - -); diff --git a/x-pack/plugins/security_solution_serverless/public/navigation/navigation_tree/navigation_tree.test.ts b/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/navigation_tree.test.ts similarity index 100% rename from x-pack/plugins/security_solution_serverless/public/navigation/navigation_tree/navigation_tree.test.ts rename to x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/navigation_tree.test.ts diff --git a/x-pack/plugins/security_solution_serverless/public/navigation/navigation_tree/navigation_tree.ts b/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/navigation_tree.ts similarity index 100% rename from x-pack/plugins/security_solution_serverless/public/navigation/navigation_tree/navigation_tree.ts rename to x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/navigation_tree.ts diff --git a/x-pack/plugins/security_solution_serverless/public/navigation/project_navigation/project_navigation.tsx b/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/project_navigation.tsx similarity index 91% rename from x-pack/plugins/security_solution_serverless/public/navigation/project_navigation/project_navigation.tsx rename to x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/project_navigation.tsx index 0986fbe7c3075..1826de0f5779d 100644 --- a/x-pack/plugins/security_solution_serverless/public/navigation/project_navigation/project_navigation.tsx +++ b/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/project_navigation.tsx @@ -14,9 +14,9 @@ import { map } from 'rxjs'; import type { NavigationTreeDefinition } from '@kbn/core-chrome-browser'; import { withServicesProvider, type Services } from '../../common/services'; -import { useFormattedSideNavItems } from '../side_navigation/use_side_nav_items'; +import { usePanelSideNavItems } from './use_panel_side_nav_items'; import { CATEGORIES, FOOTER_CATEGORIES } from '../categories'; -import { formatNavigationTree } from '../navigation_tree/navigation_tree'; +import { formatNavigationTree } from './navigation_tree'; const getPanelContentProvider = (services: Services): React.FC => { const projectNavLinks$ = services.getProjectNavLinks$(); @@ -29,7 +29,7 @@ const getPanelContentProvider = (services: Services): React.FC item.id === linkId); const { title = '', links = [], categories } = currentPanelItem ?? {}; - const items = useFormattedSideNavItems(links); + const items = usePanelSideNavItems(links); if (items.length === 0) { return null; diff --git a/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/side_navigation.test.tsx b/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/side_navigation.test.tsx deleted file mode 100644 index c22fce30419de..0000000000000 --- a/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/side_navigation.test.tsx +++ /dev/null @@ -1,183 +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 React from 'react'; -import { render } from '@testing-library/react'; -import { APP_UI_ID } from '@kbn/security-solution-plugin/common'; -import { SecurityPageName } from '@kbn/security-solution-navigation'; -import { SecuritySideNavigation } from './side_navigation'; -import { useSideNavItems } from './use_side_nav_items'; -import type { ChromeProjectNavigationNode } from '@kbn/core-chrome-browser'; -import { ExternalPageName } from '../links/constants'; -import { I18nProvider } from '@kbn/i18n-react'; - -jest.mock('./use_side_nav_items'); -jest.mock('../../common/services'); - -const mockUseSideNavItems = useSideNavItems as jest.Mock; - -const mockSolutionSideNav = jest.fn((_props: unknown) =>
); -jest.mock('@kbn/security-solution-side-nav', () => ({ - ...jest.requireActual('@kbn/security-solution-side-nav'), - SolutionSideNav: (props: unknown) => mockSolutionSideNav(props), -})); - -const mockSideNavigationFooter = jest.fn((_props: unknown) => ( -
-)); -jest.mock('./side_navigation_footer', () => ({ - ...jest.requireActual('./side_navigation_footer'), - SideNavigationFooter: (props: unknown) => mockSideNavigationFooter(props), -})); - -const sideNavItems = [ - { - id: SecurityPageName.dashboards, - label: 'Dashboards', - href: '/dashboards', - position: 'top', - onClick: jest.fn(), - }, - { - id: SecurityPageName.alerts, - label: 'Alerts', - href: '/alerts', - position: 'top', - onClick: jest.fn(), - }, - { - id: SecurityPageName.administration, - label: 'Manage', - href: '/administration', - position: 'bottom', - onClick: jest.fn(), - }, -]; - -describe('SecuritySideNavigation', () => { - beforeEach(() => { - mockUseSideNavItems.mockReturnValue(sideNavItems); - jest.clearAllMocks(); - }); - - it('should render loading when not items received', () => { - mockUseSideNavItems.mockReturnValue([]); - const component = render(, { - wrapper: I18nProvider, - }); - expect(component.queryByTestId('sideNavLoader')).toBeInTheDocument(); - }); - - it('should not render loading when items received', () => { - const component = render(, { - wrapper: I18nProvider, - }); - expect(component.queryByTestId('sideNavLoader')).not.toBeInTheDocument(); - }); - - it('should render the SideNav when items received', () => { - const component = render(, { - wrapper: I18nProvider, - }); - expect(component.queryByTestId('solutionSideNav')).toBeInTheDocument(); - }); - - it('should render the SideNav footer when items received', () => { - const component = render(, { - wrapper: I18nProvider, - }); - expect(component.queryByTestId('solutionSideNavFooter')).toBeInTheDocument(); - }); - - it('should pass only top items to the SolutionSideNav component', () => { - render(, { wrapper: I18nProvider }); - - expect(mockSolutionSideNav).toHaveBeenCalledWith( - expect.objectContaining({ - items: [ - expect.objectContaining({ id: SecurityPageName.dashboards }), - expect.objectContaining({ id: SecurityPageName.alerts }), - ], - }) - ); - }); - - it('should pass only bottom items to the SideNavigationFooter component', () => { - render(, { wrapper: I18nProvider }); - - expect(mockSideNavigationFooter).toHaveBeenCalledWith( - expect.objectContaining({ - items: [expect.objectContaining({ id: SecurityPageName.administration })], - }) - ); - }); - - it('should set empty selectedId', () => { - render(, { wrapper: I18nProvider }); - - expect(mockSolutionSideNav).toHaveBeenCalledWith( - expect.objectContaining({ - selectedId: '', - }) - ); - expect(mockSideNavigationFooter).toHaveBeenCalledWith( - expect.objectContaining({ - activeNodeId: '', - }) - ); - }); - - it('should set root external selectedId', () => { - const activeNodes = [[{ id: 'dev_tools' }]] as ChromeProjectNavigationNode[][]; - render(, { wrapper: I18nProvider }); - - expect(mockSolutionSideNav).toHaveBeenCalledWith( - expect.objectContaining({ - selectedId: ExternalPageName.devTools, - }) - ); - expect(mockSideNavigationFooter).toHaveBeenCalledWith( - expect.objectContaining({ - activeNodeId: 'dev_tools', - }) - ); - }); - - it('should set external page selectedId', () => { - const activeNodes = [[{ id: `ml:overview` }]] as ChromeProjectNavigationNode[][]; - render(, { wrapper: I18nProvider }); - - expect(mockSolutionSideNav).toHaveBeenCalledWith( - expect.objectContaining({ - selectedId: ExternalPageName.mlOverview, - }) - ); - expect(mockSideNavigationFooter).toHaveBeenCalledWith( - expect.objectContaining({ - activeNodeId: 'ml:overview', - }) - ); - }); - - it('should set internal selectedId', () => { - const activeNodes = [ - [{ id: `${APP_UI_ID}:${SecurityPageName.alerts}` }], - ] as ChromeProjectNavigationNode[][]; - render(, { wrapper: I18nProvider }); - - expect(mockSolutionSideNav).toHaveBeenCalledWith( - expect.objectContaining({ - selectedId: SecurityPageName.alerts, - }) - ); - expect(mockSideNavigationFooter).toHaveBeenCalledWith( - expect.objectContaining({ - activeNodeId: 'securitySolutionUI:alerts', - }) - ); - }); -}); diff --git a/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/side_navigation.tsx b/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/side_navigation.tsx deleted file mode 100644 index 3d87403b0ff3c..0000000000000 --- a/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/side_navigation.tsx +++ /dev/null @@ -1,116 +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 React, { useMemo } from 'react'; -import type { EuiCollapsibleNavItemProps } from '@elastic/eui'; -import { - EuiCollapsibleNavBeta, - EuiCollapsibleNavItem, - EuiLoadingSpinner, - useEuiTheme, -} from '@elastic/eui'; -import type { SideNavComponent } from '@kbn/core-chrome-browser'; -import type { SolutionSideNavItem } from '@kbn/security-solution-side-nav'; -import { SolutionSideNav, SolutionSideNavItemPosition } from '@kbn/security-solution-side-nav'; -import { useObservable } from 'react-use'; -import { css } from '@emotion/react'; -import { partition } from 'lodash/fp'; -import { useSideNavItems } from './use_side_nav_items'; -import { CATEGORIES, FOOTER_CATEGORIES } from '../categories'; -import { getProjectPageNameFromNavLinkId } from '../links/util'; -import { useKibana } from '../../common/services'; -import { SideNavigationFooter } from './side_navigation_footer'; - -const getEuiNavItemFromSideNavItem = (sideNavItem: SolutionSideNavItem, selectedId: string) => ({ - id: sideNavItem.id, - title: sideNavItem.label, - isSelected: sideNavItem.id === selectedId, - href: sideNavItem.href, - onClick: sideNavItem.onClick, -}); - -export const SecuritySideNavigation: SideNavComponent = React.memo(function SecuritySideNavigation({ - activeNodes: [activeChromeNodes], -}) { - const { chrome } = useKibana().services; - const { euiTheme } = useEuiTheme(); - const hasHeaderBanner = useObservable(chrome.hasHeaderBanner$()); - const isCollapsed = useObservable(chrome.getIsSideNavCollapsed$()); - - const items = useSideNavItems(); - - const isLoading = items.length === 0; - // we only care about the first node to highlight a left nav main item - const activeNodeId = activeChromeNodes?.[0].id ?? ''; - - const panelTopOffset = useMemo( - () => - hasHeaderBanner - ? `calc((${euiTheme.size.l} * 2) + ${euiTheme.size.xl})` - : `calc(${euiTheme.size.l} * 2)`, - [hasHeaderBanner, euiTheme] - ); - - const selectedId = useMemo( - () => (activeNodeId ? getProjectPageNameFromNavLinkId(activeNodeId) : ''), - [activeNodeId] - ); - - const bodyStyle = css` - padding-left: calc(${euiTheme.size.xl} + ${euiTheme.size.s}); - padding-right: ${euiTheme.size.s}; - `; - - const collapsedBodyItems = useMemo(() => { - return CATEGORIES.reduce((links, category) => { - const categoryLinks = items.filter((item) => category.linkIds.includes(item.id)); - links.push(...categoryLinks.map((link) => getEuiNavItemFromSideNavItem(link, selectedId))); - return links; - }, []); - }, [items, selectedId]); - - const [bodyItems, footerItems] = useMemo( - () => partition((item) => item.position === SolutionSideNavItemPosition.top, items), - [items] - ); - - return isLoading ? ( - - ) : ( - <> - - - {!isCollapsed && ( -
- -
- )} -
- - - - - ); -}); - -// eslint-disable-next-line import/no-default-export -export default SecuritySideNavigation; diff --git a/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/side_navigation_footer.test.tsx b/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/side_navigation_footer.test.tsx deleted file mode 100644 index fdfd3216d606d..0000000000000 --- a/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/side_navigation_footer.test.tsx +++ /dev/null @@ -1,153 +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 React from 'react'; -import { render } from '@testing-library/react'; -import { SecurityPageName } from '@kbn/security-solution-navigation'; -import { SideNavigationFooter } from './side_navigation_footer'; -import { ExternalPageName } from '../links/constants'; -import { I18nProvider } from '@kbn/i18n-react'; -import type { ProjectSideNavItem } from './types'; -import { FOOTER_CATEGORIES } from '../categories'; - -jest.mock('../../common/services'); - -const items: ProjectSideNavItem[] = [ - { - id: SecurityPageName.landing, - label: 'Get Started', - href: '/landing', - }, - { - id: ExternalPageName.devTools, - label: 'Developer tools', - href: '/dev_tools', - }, - { - id: ExternalPageName.management, - label: 'Management', - href: '/management', - }, - { - id: ExternalPageName.integrationsSecurity, - label: 'Integrations', - href: '/integrations', - }, - { - id: ExternalPageName.cloudUsersAndRoles, - label: 'Users and roles', - href: '/cloud/users_and_roles', - }, - { - id: ExternalPageName.cloudBilling, - label: 'Billing and subscription', - href: '/cloud/billing', - }, -]; - -describe('SideNavigationFooter', () => { - beforeEach(() => { - jest.clearAllMocks(); - }); - - it('should render all the items', () => { - const component = render( - , - { - wrapper: I18nProvider, - } - ); - - items.forEach((item) => { - expect(component.queryByTestId(`solutionSideNavItemLink-${item.id}`)).toBeInTheDocument(); - }); - }); - - it('should highlight the active node', () => { - const component = render( - , - { - wrapper: I18nProvider, - } - ); - - items.forEach((item) => { - const isSelected = component - .queryByTestId(`solutionSideNavItemLink-${item.id}`) - ?.className.includes('isSelected'); - - if (item.id === ExternalPageName.devTools) { - expect(isSelected).toBe(true); - } else { - expect(isSelected).toBe(false); - } - }); - }); - - it('should highlight the active node inside the collapsible', () => { - const component = render( - , - { - wrapper: I18nProvider, - } - ); - - items.forEach((item) => { - const isSelected = component - .queryByTestId(`solutionSideNavItemLink-${item.id}`) - ?.className.includes('isSelected'); - - if (item.id === ExternalPageName.management) { - expect(isSelected).toBe(true); - } else { - expect(isSelected).toBe(false); - } - }); - }); - - it('should render closed collapsible if it has no active node', () => { - const component = render( - , - { - wrapper: I18nProvider, - } - ); - - const isOpen = component - .queryByTestId('navFooterCollapsible-project-settings') - ?.className.includes('euiAccordion-isOpen'); - - expect(isOpen).toBe(false); - }); - - it('should open collapsible if it has an active node', () => { - const component = render( - , - { - wrapper: I18nProvider, - } - ); - - const isOpen = component - .queryByTestId('navFooterCollapsible-project-settings') - ?.className.includes('euiAccordion-isOpen'); - - expect(isOpen).toBe(true); - }); -}); diff --git a/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/side_navigation_footer.tsx b/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/side_navigation_footer.tsx deleted file mode 100644 index 0ed8c1e80f256..0000000000000 --- a/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/side_navigation_footer.tsx +++ /dev/null @@ -1,135 +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 React, { useEffect, useMemo, useState } from 'react'; -import type { EuiCollapsibleNavSubItemProps, IconType } from '@elastic/eui'; -import { EuiCollapsibleNavItem } from '@elastic/eui'; -import { - isAccordionLinkCategory, - isSeparatorLinkCategory, - type LinkCategory, -} from '@kbn/security-solution-navigation'; -import { getNavLinkIdFromProjectPageName } from '../links/util'; -import type { ProjectSideNavItem } from './types'; - -export const SideNavigationFooter: React.FC<{ - activeNodeId: string; - items: ProjectSideNavItem[]; - categories: LinkCategory[]; -}> = ({ activeNodeId, items, categories }) => { - return ( - <> - {categories.map((category, index) => { - const categoryItems = - category.linkIds?.reduce((acc, linkId) => { - const item = items.find(({ id }) => id === linkId); - if (item) { - acc.push(item); - } - return acc; - }, []) ?? []; - - if (isSeparatorLinkCategory(category)) { - return ( - - ); - } - if (isAccordionLinkCategory(category)) { - return ( - - ); - } - return null; - })} - - ); -}; - -const SideNavigationFooterStandalone: React.FC<{ - items: ProjectSideNavItem[]; - activeNodeId: string; -}> = ({ items, activeNodeId }) => ( - <> - {items.map((item) => ( - - ))} - -); - -const SideNavigationFooterCollapsible: React.FC<{ - title: string; - items: ProjectSideNavItem[]; - activeNodeId: string; - icon?: IconType; -}> = ({ title, icon, items, activeNodeId }) => { - const hasSelected = useMemo( - () => items.some(({ id }) => getNavLinkIdFromProjectPageName(id) === activeNodeId), - [activeNodeId, items] - ); - const [isOpen, setIsOpen] = useState(hasSelected); - const categoryId = useMemo(() => (title ?? '').toLowerCase().replace(' ', '-'), [title]); - - useEffect(() => { - setIsOpen((open) => (!open ? hasSelected : true)); - }, [hasSelected]); - - return ( - { - setIsOpen(open); - }, - }} - items={items.map((item) => formatCollapsibleItem(item, activeNodeId))} - /> - ); -}; - -const formatCollapsibleItem = ( - sideNavItem: ProjectSideNavItem, - activeNodeId: string -): EuiCollapsibleNavSubItemProps => { - return { - 'data-test-subj': `solutionSideNavItemLink-${sideNavItem.id}`, - id: sideNavItem.id, - title: sideNavItem.label, - isSelected: getNavLinkIdFromProjectPageName(sideNavItem.id) === activeNodeId, - href: sideNavItem.href, - ...(sideNavItem.openInNewTab && { target: '_blank' }), - onClick: sideNavItem.onClick, - icon: sideNavItem.iconType, - iconProps: { size: 's' }, - }; -}; diff --git a/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/use_side_nav_items.test.tsx b/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/use_panel_side_nav_items.test.tsx similarity index 64% rename from x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/use_side_nav_items.test.tsx rename to x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/use_panel_side_nav_items.test.tsx index abb82cc209313..306f31416088f 100644 --- a/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/use_side_nav_items.test.tsx +++ b/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/use_panel_side_nav_items.test.tsx @@ -6,13 +6,11 @@ */ import { renderHook } from '@testing-library/react-hooks'; -import { useSideNavItems } from './use_side_nav_items'; +import { usePanelSideNavItems } from './use_panel_side_nav_items'; import { SecurityPageName } from '@kbn/security-solution-navigation'; -import { mockServices, mockProjectNavLinks } from '../../common/services/__mocks__/services.mock'; import { ExternalPageName } from '../links/constants'; jest.mock('@kbn/security-solution-navigation/src/navigation'); -jest.mock('../../common/services'); const mockUseLocation = jest.fn(() => ({ pathname: '/' })); jest.mock('react-router-dom', () => ({ @@ -20,25 +18,24 @@ jest.mock('react-router-dom', () => ({ useLocation: () => mockUseLocation(), })); -describe('useSideNavItems', () => { +describe('usePanelSideNavItems', () => { beforeEach(() => { jest.clearAllMocks(); }); it('should return empty items', async () => { - const { result } = renderHook(useSideNavItems); + const { result } = renderHook(usePanelSideNavItems, { initialProps: [] }); const items = result.current; - expect(items).toEqual([]); - expect(mockServices.getProjectNavLinks$).toHaveBeenCalledTimes(1); }); it('should return main items', async () => { - mockProjectNavLinks.mockReturnValueOnce([ - { id: SecurityPageName.alerts, title: 'Alerts' }, - { id: SecurityPageName.case, title: 'Cases' }, - ]); - const { result } = renderHook(useSideNavItems); + const { result } = renderHook(usePanelSideNavItems, { + initialProps: [ + { id: SecurityPageName.alerts, title: 'Alerts' }, + { id: SecurityPageName.case, title: 'Cases' }, + ], + }); const items = result.current; expect(items).toEqual([ @@ -58,14 +55,15 @@ describe('useSideNavItems', () => { }); it('should return secondary items', async () => { - mockProjectNavLinks.mockReturnValueOnce([ - { - id: SecurityPageName.dashboards, - title: 'Dashboards', - links: [{ id: SecurityPageName.detectionAndResponse, title: 'Detection & Response' }], - }, - ]); - const { result } = renderHook(useSideNavItems); + const { result } = renderHook(usePanelSideNavItems, { + initialProps: [ + { + id: SecurityPageName.dashboards, + title: 'Dashboards', + links: [{ id: SecurityPageName.detectionAndResponse, title: 'Detection & Response' }], + }, + ], + }); const items = result.current; expect(items).toEqual([ @@ -86,14 +84,15 @@ describe('useSideNavItems', () => { }); it('should return get started link', async () => { - mockProjectNavLinks.mockReturnValueOnce([ - { - id: SecurityPageName.landing, - title: 'Get Started', - sideNavIcon: 'launch', - }, - ]); - const { result } = renderHook(useSideNavItems); + const { result } = renderHook(usePanelSideNavItems, { + initialProps: [ + { + id: SecurityPageName.landing, + title: 'Get Started', + sideNavIcon: 'launch', + }, + ], + }); const items = result.current; @@ -109,15 +108,16 @@ describe('useSideNavItems', () => { }); it('should openInNewTab for external (cloud) links', async () => { - mockProjectNavLinks.mockReturnValueOnce([ - { - id: ExternalPageName.cloudUsersAndRoles, - externalUrl: 'https://cloud.elastic.co/users_roles', - title: 'Users & Roles', - sideNavIcon: 'someicon', - }, - ]); - const { result } = renderHook(useSideNavItems); + const { result } = renderHook(usePanelSideNavItems, { + initialProps: [ + { + id: ExternalPageName.cloudUsersAndRoles, + externalUrl: 'https://cloud.elastic.co/users_roles', + title: 'Users & Roles', + sideNavIcon: 'someicon', + }, + ], + }); const items = result.current; diff --git a/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/use_side_nav_items.ts b/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/use_panel_side_nav_items.ts similarity index 83% rename from x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/use_side_nav_items.ts rename to x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/use_panel_side_nav_items.ts index 32945e89765e1..5824f28137d16 100644 --- a/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/use_side_nav_items.ts +++ b/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/use_panel_side_nav_items.ts @@ -9,7 +9,6 @@ import { useCallback, useMemo } from 'react'; import { type NavigationLink } from '@kbn/security-solution-navigation'; import { useGetLinkProps } from '@kbn/security-solution-navigation/links'; import { SolutionSideNavItemPosition } from '@kbn/security-solution-side-nav'; -import { useNavLinks } from '../../common/hooks/use_nav_links'; import type { ProjectSideNavItem } from './types'; import type { ProjectNavigationLink, ProjectPageName } from '../links/types'; import { isBottomNavItemId } from '../links/util'; @@ -53,19 +52,9 @@ const formatLink = ( }; /** - * Returns all the formatted SideNavItems, including external links + * Returns all the formatted SideNavItems for the panel, including external links */ -export const useSideNavItems = (): ProjectSideNavItem[] => { - const navLinks = useNavLinks(); - return useFormattedSideNavItems(navLinks); -}; - -/** - * Returns all the formatted SideNavItems, including external links - */ -export const useFormattedSideNavItems = ( - navLinks: ProjectNavigationLink[] -): ProjectSideNavItem[] => { +export const usePanelSideNavItems = (navLinks: ProjectNavigationLink[]): ProjectSideNavItem[] => { const getKibanaLinkProps = useGetLinkProps(); const getLinkProps = useCallback( diff --git a/x-pack/plugins/security_solution_serverless/public/navigation/navigation_tree/utils.ts b/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/utils.ts similarity index 100% rename from x-pack/plugins/security_solution_serverless/public/navigation/navigation_tree/utils.ts rename to x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/utils.ts diff --git a/x-pack/plugins/security_solution_serverless/tsconfig.json b/x-pack/plugins/security_solution_serverless/tsconfig.json index a626590c08e1a..a9f558d87def2 100644 --- a/x-pack/plugins/security_solution_serverless/tsconfig.json +++ b/x-pack/plugins/security_solution_serverless/tsconfig.json @@ -23,8 +23,6 @@ "@kbn/security-solution-side-nav", "@kbn/security-solution-navigation", "@kbn/security-solution-upselling", - "@kbn/default-nav-ml", - "@kbn/default-nav-devtools", "@kbn/kibana-react-plugin", "@kbn/core-chrome-browser", "@kbn/i18n-react",