Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[navigation]fix: redirect user to home in global when workspace is enabled #7551

Merged
merged 9 commits into from
Jul 30, 2024
2 changes: 2 additions & 0 deletions changelogs/fragments/7551.yml
Original file line number Diff line number Diff line change
@@ -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))
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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 || [],
Expand Down Expand Up @@ -269,7 +273,7 @@ export function CollapsibleNavGroupEnabled({
});

return fulfillRegistrationLinksToChromeNavLinks(navLinksForAll, navLinks);
}, [navLinks, navGroupsMap, currentNavGroup]);
}, [navLinks, navGroupsMap, currentNavGroup, visibleUseCases]);

const width = useMemo(() => {
if (!isNavOpen) {
Expand Down Expand Up @@ -332,13 +336,13 @@ export function CollapsibleNavGroupEnabled({
<>
<CollapsibleNavTop
navLinks={navLinks}
navGroupsMap={navGroupsMap}
navigateToApp={navigateToApp}
logos={logos}
onClickBack={() => setCurrentNavGroup(undefined)}
currentNavGroup={currentNavGroup}
shouldShrinkNavigation={!isNavOpen}
onClickShrink={closeNav}
visibleUseCases={visibleUseCases}
/>
<NavGroups
navLinks={navLinksForRender}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,9 @@ describe('<CollapsibleNavTop />', () => {
return {
navLinks: mockedNavLinks,
navigateToApp: jest.fn(),
navGroupsMap: {},
logos: getLogos({}, mockBasePath.serverBasePath),
shouldShrinkNavigation: false,
visibleUseCases: [],
};
};
it('should render home icon', async () => {
Expand All @@ -74,23 +74,23 @@ describe('<CollapsibleNavTop />', () => {
});

it('should render back icon', async () => {
const { findByTestId } = render(
const { findByTestId, findByText } = render(
<CollapsibleNavTop
{...getMockedProps()}
navGroupsMap={{
navGroupFoo: {
visibleUseCases={[
{
id: 'navGroupFoo',
title: 'navGroupFoo',
description: 'navGroupFoo',
navLinks: [],
},
navGroupBar: {
{
id: 'navGroupBar',
title: 'navGroupBar',
description: 'navGroupBar',
navLinks: [],
},
}}
]}
currentNavGroup={{
id: 'navGroupFoo',
title: 'navGroupFoo',
Expand All @@ -100,6 +100,37 @@ describe('<CollapsibleNavTop />', () => {
/>
);
await findByTestId('collapsibleNavBackButton');
await findByText('Back');
});

it('should render back home icon', async () => {
const { findByTestId, findByText } = render(
<CollapsibleNavTop
{...getMockedProps()}
visibleUseCases={[
{
id: 'navGroupFoo',
title: 'navGroupFoo',
description: 'navGroupFoo',
navLinks: [],
},
{
id: 'navGroupBar',
title: 'navGroupBar',
description: 'navGroupBar',
navLinks: [],
},
]}
currentNavGroup={{
id: 'global',
title: 'navGroupFoo',
description: 'navGroupFoo',
navLinks: [],
}}
/>
);
await findByTestId('collapsibleNavBackButton');
await findByText('Home');
});

it('should render expand icon', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,46 +22,59 @@ import { ALL_USE_CASE_ID } from '../../../../../core/utils';

export interface CollapsibleNavTopProps {
navLinks: ChromeNavLink[];
navGroupsMap: Record<string, NavGroupItemInMap>;
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;

return !shouldShowBackButton;
}, [shouldShowBackButton, homeLink, shouldShrinkNavigation]);

const homeLinkProps = useMemo(() => {
if (shouldShowHomeLink) {
if (homeLink) {
const propsForHomeIcon = createEuiListItem({
link: homeLink as ChromeNavLink,
link: homeLink,
appId: 'home',
dataTestSubj: 'collapsibleNavHome',
navigateToApp,
Expand All @@ -74,7 +87,7 @@ export const CollapsibleNavTop = ({
}

return {};
}, [shouldShowHomeLink, homeLink, navigateToApp]);
}, [homeLink, navigateToApp]);

return (
<div className="side-naivgation-top">
Expand All @@ -91,13 +104,17 @@ export const CollapsibleNavTop = ({
<EuiFlexItem grow={false}>
<EuiButtonEmpty
size="l"
onClick={onClickBack}
onClick={isInGlobalWorkspace ? homeLinkProps.onClick : onClickBack}
data-test-subj="collapsibleNavBackButton"
>
<EuiIcon type="arrowLeft" />
{i18n.translate('core.ui.primaryNav.backButtonLabel', {
defaultMessage: 'Back',
})}
{isInGlobalWorkspace
? i18n.translate('core.ui.primaryNav.homeButtonLabel', {
defaultMessage: 'Home',
})
: i18n.translate('core.ui.primaryNav.backButtonLabel', {
defaultMessage: 'Back',
})}
</EuiButtonEmpty>
</EuiFlexItem>
) : null}
Expand Down
23 changes: 23 additions & 0 deletions src/plugins/dev_tools/public/dev_tools_icon.test.tsx
Original file line number Diff line number Diff line change
@@ -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('<DevToolsIcon />', () => {
it('should call chrome.navGroup.setCurrentNavGroup and application.navigateToApp methods from core service when click', () => {
const coreStartMock = coreMock.createStart();
const { container } = render(<DevToolsIcon core={coreStartMock} appId="foo" />);
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');
});
});
9 changes: 8 additions & 1 deletion src/plugins/dev_tools/public/dev_tools_icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
<EuiButtonIcon
aria-label="go-to-dev-tools"
iconType="consoleApp"
onClick={() => 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);
}}
/>
);
}
Loading