diff --git a/changelogs/fragments/7551.yml b/changelogs/fragments/7551.yml new file mode 100644 index 00000000000..0f5db1a9f3c --- /dev/null +++ b/changelogs/fragments/7551.yml @@ -0,0 +1,2 @@ +fix: +- [navigation]feat: redirect user to home in global when workspace is enabled ([#7551](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/7551)) \ No newline at end of file diff --git a/src/core/public/chrome/ui/header/collapsible_nav_group_enabled.tsx b/src/core/public/chrome/ui/header/collapsible_nav_group_enabled.tsx index 342cee5f273..c0d2a87635e 100644 --- a/src/core/public/chrome/ui/header/collapsible_nav_group_enabled.tsx +++ b/src/core/public/chrome/ui/header/collapsible_nav_group_enabled.tsx @@ -198,6 +198,14 @@ export function CollapsibleNavGroupEnabled({ const navGroupsMap = useObservable(observables.navGroupsMap$, {}); const currentNavGroup = useObservable(observables.currentNavGroup$, undefined); + const visibleUseCases = useMemo( + () => + Object.values(navGroupsMap).filter( + (group) => group.type === undefined && group.status !== NavGroupStatus.Hidden + ), + [navGroupsMap] + ); + const navLinksForRender: ChromeNavLink[] = useMemo(() => { if (currentNavGroup && currentNavGroup.id !== ALL_USE_CASE_ID) { return fulfillRegistrationLinksToChromeNavLinks( @@ -206,10 +214,6 @@ export function CollapsibleNavGroupEnabled({ ); } - const visibleUseCases = Object.values(navGroupsMap).filter( - (group) => group.type === undefined && group.status !== NavGroupStatus.Hidden - ); - if (visibleUseCases.length === 1) { return fulfillRegistrationLinksToChromeNavLinks( navGroupsMap[visibleUseCases[0].id].navLinks || [], @@ -269,7 +273,7 @@ export function CollapsibleNavGroupEnabled({ }); return fulfillRegistrationLinksToChromeNavLinks(navLinksForAll, navLinks); - }, [navLinks, navGroupsMap, currentNavGroup]); + }, [navLinks, navGroupsMap, currentNavGroup, visibleUseCases]); const width = useMemo(() => { if (!isNavOpen) { @@ -332,13 +336,13 @@ export function CollapsibleNavGroupEnabled({ <> setCurrentNavGroup(undefined)} currentNavGroup={currentNavGroup} shouldShrinkNavigation={!isNavOpen} onClickShrink={closeNav} + visibleUseCases={visibleUseCases} /> ', () => { return { navLinks: mockedNavLinks, navigateToApp: jest.fn(), - navGroupsMap: {}, logos: getLogos({}, mockBasePath.serverBasePath), shouldShrinkNavigation: false, + visibleUseCases: [], }; }; it('should render home icon', async () => { @@ -74,23 +74,23 @@ describe('', () => { }); it('should render back icon', async () => { - const { findByTestId } = render( + const { findByTestId, findByText } = render( ', () => { /> ); await findByTestId('collapsibleNavBackButton'); + await findByText('Back'); + }); + + it('should render back home icon', async () => { + const { findByTestId, findByText } = render( + + ); + await findByTestId('collapsibleNavBackButton'); + await findByText('Home'); }); it('should render expand icon', async () => { diff --git a/src/core/public/chrome/ui/header/collapsible_nav_group_enabled_top.tsx b/src/core/public/chrome/ui/header/collapsible_nav_group_enabled_top.tsx index 568290da727..396d78a1024 100644 --- a/src/core/public/chrome/ui/header/collapsible_nav_group_enabled_top.tsx +++ b/src/core/public/chrome/ui/header/collapsible_nav_group_enabled_top.tsx @@ -22,36 +22,49 @@ import { ALL_USE_CASE_ID } from '../../../../../core/utils'; export interface CollapsibleNavTopProps { navLinks: ChromeNavLink[]; - navGroupsMap: Record; currentNavGroup?: NavGroupItemInMap; navigateToApp: InternalApplicationStart['navigateToApp']; logos: Logos; onClickBack?: () => void; onClickShrink?: () => void; shouldShrinkNavigation: boolean; + visibleUseCases: NavGroupItemInMap[]; } export const CollapsibleNavTop = ({ navLinks, - navGroupsMap, currentNavGroup, navigateToApp, logos, onClickBack, onClickShrink, shouldShrinkNavigation, + visibleUseCases, }: CollapsibleNavTopProps) => { const homeLink = useMemo(() => navLinks.find((link) => link.id === 'home'), [navLinks]); - const shouldShowBackButton = useMemo( - () => - currentNavGroup?.id !== ALL_USE_CASE_ID && - !shouldShrinkNavigation && - Object.values(navGroupsMap).filter((item) => !item.type).length > 1 && - currentNavGroup, - [navGroupsMap, currentNavGroup, shouldShrinkNavigation] + const isOutsideWorkspace = useMemo( + () => !visibleUseCases.find((useCase) => useCase.id === currentNavGroup?.id), + [currentNavGroup, visibleUseCases] ); + const shouldShowBackButton = useMemo(() => { + if (!currentNavGroup || currentNavGroup.id === ALL_USE_CASE_ID || shouldShrinkNavigation) { + return false; + } + + // It means user is in a specific type of workspace + if (visibleUseCases.length <= 1) { + return false; + } + + if (isOutsideWorkspace) { + return true; + } + + return visibleUseCases.length > 1; + }, [visibleUseCases, currentNavGroup, shouldShrinkNavigation, isOutsideWorkspace]); + const shouldShowHomeLink = useMemo(() => { if (!homeLink || shouldShrinkNavigation) return false; @@ -59,9 +72,9 @@ export const CollapsibleNavTop = ({ }, [shouldShowBackButton, homeLink, shouldShrinkNavigation]); const homeLinkProps = useMemo(() => { - if (shouldShowHomeLink) { + if (homeLink) { const propsForHomeIcon = createEuiListItem({ - link: homeLink as ChromeNavLink, + link: homeLink, appId: 'home', dataTestSubj: 'collapsibleNavHome', navigateToApp, @@ -74,7 +87,7 @@ export const CollapsibleNavTop = ({ } return {}; - }, [shouldShowHomeLink, homeLink, navigateToApp]); + }, [homeLink, navigateToApp]); return (
@@ -91,13 +104,17 @@ export const CollapsibleNavTop = ({ - {i18n.translate('core.ui.primaryNav.backButtonLabel', { - defaultMessage: 'Back', - })} + {isOutsideWorkspace + ? i18n.translate('core.ui.primaryNav.homeButtonLabel', { + defaultMessage: 'Home', + }) + : i18n.translate('core.ui.primaryNav.backButtonLabel', { + defaultMessage: 'Back', + })} ) : null} diff --git a/src/plugins/dev_tools/public/dev_tools_icon.test.tsx b/src/plugins/dev_tools/public/dev_tools_icon.test.tsx new file mode 100644 index 00000000000..47d9a621600 --- /dev/null +++ b/src/plugins/dev_tools/public/dev_tools_icon.test.tsx @@ -0,0 +1,23 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import React from 'react'; +import { fireEvent, render } from '@testing-library/react'; +import { DevToolsIcon } from './dev_tools_icon'; +import { coreMock } from '../../../core/public/mocks'; +import { DEFAULT_NAV_GROUPS } from '../../../core/public'; + +describe('', () => { + it('should call chrome.navGroup.setCurrentNavGroup and application.navigateToApp methods from core service when click', () => { + const coreStartMock = coreMock.createStart(); + const { container } = render(); + const component = container.children[0]; + fireEvent.click(component); + expect(coreStartMock.chrome.navGroup.setCurrentNavGroup).toBeCalledWith( + DEFAULT_NAV_GROUPS.dataAdministration.id + ); + expect(coreStartMock.application.navigateToApp).toBeCalledWith('foo'); + }); +}); diff --git a/src/plugins/dev_tools/public/dev_tools_icon.tsx b/src/plugins/dev_tools/public/dev_tools_icon.tsx index 933b7af0037..b58ef03473a 100644 --- a/src/plugins/dev_tools/public/dev_tools_icon.tsx +++ b/src/plugins/dev_tools/public/dev_tools_icon.tsx @@ -6,13 +6,20 @@ import React from 'react'; import { EuiButtonIcon } from '@elastic/eui'; import { CoreStart } from 'opensearch-dashboards/public'; +import { DEFAULT_NAV_GROUPS } from '../../../core/public'; export function DevToolsIcon({ core, appId }: { core: CoreStart; appId: string }) { return ( core.application.navigateToApp(appId)} + onClick={() => { + /** + * This is a workaround in 2.16, once devTools being refactor to a drawer, we can remove the setCurrentNavGroup line. + */ + core.chrome.navGroup.setCurrentNavGroup(DEFAULT_NAV_GROUPS.dataAdministration.id); + core.application.navigateToApp(appId); + }} /> ); }