Skip to content

Commit

Permalink
[navigation]fix: redirect user to home in global when workspace is en…
Browse files Browse the repository at this point in the history
…abled (#7551)

* feat: redirect user to home when in global

Signed-off-by: SuZhou-Joe <suzhou@amazon.com>

* Changeset file for PR #7551 created/updated

* Changeset file for PR #7551 created/updated

* feat: add some comment

Signed-off-by: SuZhou-Joe <suzhou@amazon.com>

* feat: remove useless change

Signed-off-by: SuZhou-Joe <suzhou@amazon.com>

* feat: optimize comment

Signed-off-by: SuZhou-Joe <suzhou@amazon.com>

* feat: optimize description and variable naming

Signed-off-by: SuZhou-Joe <suzhou@amazon.com>

* feat: update

Signed-off-by: SuZhou-Joe <suzhou@amazon.com>

---------

Signed-off-by: SuZhou-Joe <suzhou@amazon.com>
Co-authored-by: opensearch-changeset-bot[bot] <154024398+opensearch-changeset-bot[bot]@users.noreply.github.com>
Co-authored-by: Anan Zhuang <ananzh@amazon.com>
  • Loading branch information
3 people committed Jul 30, 2024
1 parent 2b7dbe0 commit 96936f3
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 29 deletions.
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))
16 changes: 10 additions & 6 deletions src/core/public/chrome/ui/header/collapsible_nav_group_enabled.tsx
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={isOutsideWorkspace ? homeLinkProps.onClick : onClickBack}
data-test-subj="collapsibleNavBackButton"
>
<EuiIcon type="arrowLeft" />
{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',
})}
</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);
}}
/>
);
}

0 comments on commit 96936f3

Please sign in to comment.