Skip to content

Commit

Permalink
[Workspace] Content menu picker in side bar and enable searching (#7881)
Browse files Browse the repository at this point in the history
* 01-feat/refractor-content-menu-picker-in-side-bar

Signed-off-by: Qxisylolo <qianxisy@amazon.com>

* 02-enable-associated-icon

Signed-off-by: Qxisylolo <qianxisy@amazon.com>

* 03-update-side-bar

Signed-off-by: Qxisylolo <qianxisy@amazon.com>

* 04-fix-bugs

Signed-off-by: Qxisylolo <qianxisy@amazon.com>

* 04-fix-bugs, add test

Signed-off-by: Qxisylolo <qianxisy@amazon.com>

* 05-delete search

Signed-off-by: Qxisylolo <qianxisy@amazon.com>

* 06-delete search

Signed-off-by: Qxisylolo <qianxisy@amazon.com>

* 06-fix-bug

Signed-off-by: Qxisylolo <qianxisy@amazon.com>

* 07-fix-conflication-1

Signed-off-by: Qxisylolo <qianxisy@amazon.com>

* 07-fix-conflication-adjust-icon-size

Signed-off-by: Qxisylolo <qianxisy@amazon.com>

* Changeset file for PR #7881 created/updated

---------

Signed-off-by: Qxisylolo <qianxisy@amazon.com>
Co-authored-by: opensearch-changeset-bot[bot] <154024398+opensearch-changeset-bot[bot]@users.noreply.github.com>
  • Loading branch information
1 parent a4470a5 commit a05c4a2
Show file tree
Hide file tree
Showing 4 changed files with 220 additions and 127 deletions.
2 changes: 2 additions & 0 deletions changelogs/fragments/7881.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
feat:
- Refactor content menu picker in side bar and enable searching ([#7881](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/7881))
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import { CoreStart, DEFAULT_NAV_GROUPS } from '../../../../../core/public';
import { BehaviorSubject } from 'rxjs';
import { IntlProvider } from 'react-intl';
import { recentWorkspaceManager } from '../../recent_workspace_manager';
import * as workspaceUtils from '../utils/workspace';

describe('<WorkspaceMenu />', () => {
let coreStartMock: CoreStart;
Expand Down Expand Up @@ -91,7 +90,52 @@ describe('<WorkspaceMenu />', () => {
expect(screen.getByTestId('workspace-menu-item-recent-workspace-2')).toBeInTheDocument();
});

it('should display current workspace name and use case name', () => {
it('should be able to display empty state when the workspace list is empty', () => {
coreStartMock.workspaces.workspaceList$.next([]);
render(<WorkspaceMenuCreatorComponent />);
const selectButton = screen.getByTestId('workspace-select-button');
fireEvent.click(selectButton);
expect(screen.getByText(/no workspace available/i)).toBeInTheDocument();
});

it('should be able to perform search and filter and the results will be shown in both all and recent section', () => {
coreStartMock.workspaces.workspaceList$.next([
{ id: 'workspace-1', name: 'workspace 1', features: [] },
{ id: 'test-2', name: 'test 2', features: [] },
]);
jest
.spyOn(recentWorkspaceManager, 'getRecentWorkspaces')
.mockReturnValue([{ id: 'workspace-1', timestamp: 1234567890 }]);
render(<WorkspaceMenuCreatorComponent />);

const selectButton = screen.getByTestId('workspace-select-button');
fireEvent.click(selectButton);

const searchInput = screen.getByRole('searchbox');
fireEvent.change(searchInput, { target: { value: 'works' } });
expect(screen.getByTestId('workspace-menu-item-recent-workspace-1')).toBeInTheDocument();
expect(screen.getByTestId('workspace-menu-item-recent-workspace-1')).toBeInTheDocument();
});

it('should be able to display empty state when seach is not found', () => {
coreStartMock.workspaces.workspaceList$.next([
{ id: 'workspace-1', name: 'workspace 1', features: [] },
{ id: 'test-2', name: 'test 2', features: [] },
]);
jest
.spyOn(recentWorkspaceManager, 'getRecentWorkspaces')
.mockReturnValue([{ id: 'workspace-1', timestamp: 1234567890 }]);
render(<WorkspaceMenuCreatorComponent />);

const selectButton = screen.getByTestId('workspace-select-button');
fireEvent.click(selectButton);

const searchInput = screen.getByRole('searchbox');
fireEvent.change(searchInput, { target: { value: 'noitems' } });
expect(screen.getByText(/no workspace available/i)).toBeInTheDocument();
});

it('should display current workspace name, use case name and associated icon', () => {
coreStartMock.workspaces.currentWorkspace$.next({
id: 'workspace-1',
name: 'workspace 1',
Expand All @@ -102,6 +146,7 @@ describe('<WorkspaceMenu />', () => {
fireEvent.click(screen.getByTestId('workspace-select-button'));
expect(screen.getByTestId('workspace-menu-current-workspace-name')).toBeInTheDocument();
expect(screen.getByTestId('workspace-menu-current-use-case')).toBeInTheDocument();
expect(screen.getByTestId('current-workspace-icon-wsObservability')).toBeInTheDocument();
expect(screen.getByText('Observability')).toBeInTheDocument();
});

Expand Down Expand Up @@ -155,28 +200,6 @@ describe('<WorkspaceMenu />', () => {
});
});

it('should navigate to workspace management page', () => {
coreStartMock.workspaces.currentWorkspace$.next({
id: 'workspace-1',
name: 'workspace 1',
features: ['use-case-observability'],
});
const navigateToWorkspaceDetail = jest.spyOn(workspaceUtils, 'navigateToWorkspaceDetail');
render(<WorkspaceMenuCreatorComponent />);

fireEvent.click(screen.getByTestId('workspace-select-button'));
const button = screen.getByText(/Manage workspace/i);
fireEvent.click(button);
expect(navigateToWorkspaceDetail).toBeCalled();
});

it('should navigate to workspaces management page', () => {
render(<WorkspaceMenuCreatorComponent />);
fireEvent.click(screen.getByTestId('workspace-select-button'));
fireEvent.click(screen.getByText(/manage workspaces/i));
expect(coreStartMock.application.navigateToApp).toHaveBeenCalledWith('workspace_list');
});

it('should navigate to create workspace page', () => {
render(<WorkspaceMenuCreatorComponent />);
fireEvent.click(screen.getByTestId('workspace-select-button'));
Expand All @@ -188,7 +211,7 @@ describe('<WorkspaceMenu />', () => {
render(<WorkspaceMenuCreatorComponent />);

fireEvent.click(screen.getByTestId('workspace-select-button'));
fireEvent.click(screen.getByText(/View all/i));
fireEvent.click(screen.getByText(/manage/i));
expect(coreStartMock.application.navigateToApp).toHaveBeenCalledWith('workspace_list');
});

Expand All @@ -203,7 +226,7 @@ describe('<WorkspaceMenu />', () => {
render(<WorkspaceMenuCreatorComponent />);

fireEvent.click(screen.getByTestId('workspace-select-button'));
expect(screen.getByText(/View all/i)).toBeInTheDocument();
expect(screen.queryByText(/manage/i)).not.toBeInTheDocument();
expect(screen.queryByText(/create workspaces/i)).toBeNull();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,20 @@ import { useObservable } from 'react-use';
import {
EuiText,
EuiPanel,
EuiButton,
EuiPopover,
EuiToolTip,
EuiFlexItem,
EuiFlexGroup,
EuiSmallButtonEmpty,
EuiSmallButton,
EuiButtonIcon,
EuiFlexItem,
EuiIcon,
EuiFlexGroup,
EuiHorizontalRule,
EuiButtonEmpty,
} from '@elastic/eui';
import { BehaviorSubject } from 'rxjs';
import { WORKSPACE_CREATE_APP_ID, WORKSPACE_LIST_APP_ID } from '../../../common/constants';
import { CoreStart, WorkspaceObject } from '../../../../../core/public';
import { getFirstUseCaseOfFeatureConfigs } from '../../utils';
import { WorkspaceUseCase } from '../../types';
import { navigateToWorkspaceDetail } from '../utils/workspace';
import { validateWorkspaceColor } from '../../../common/utils';
import { WorkspacePickerContent } from '../workspace_picker_content/workspace_picker_content';

Expand All @@ -35,16 +34,8 @@ const createWorkspaceButton = i18n.translate('workspace.menu.button.createWorksp
defaultMessage: 'Create workspace',
});

const viewAllButton = i18n.translate('workspace.menu.button.viewAll', {
defaultMessage: 'View all',
});

const manageWorkspaceButton = i18n.translate('workspace.menu.button.manageWorkspace', {
defaultMessage: 'Manage workspace',
});

const manageWorkspacesButton = i18n.translate('workspace.menu.button.manageWorkspaces', {
defaultMessage: 'Manage workspaces',
defaultMessage: 'Manage',
});

const getValidWorkspaceColor = (color?: string) =>
Expand Down Expand Up @@ -97,8 +88,9 @@ export const WorkspaceMenu = ({ coreStart, registeredUseCases$ }: Props) => {
closePopover={closePopover}
panelPaddingSize="s"
anchorPosition="downCenter"
repositionOnScroll={true}
>
<EuiPanel paddingSize="s" hasBorder={false} color="transparent">
<EuiPanel hasBorder={false} color="transparent">
<EuiFlexGroup
justifyContent="spaceAround"
alignItems="center"
Expand All @@ -109,100 +101,91 @@ export const WorkspaceMenu = ({ coreStart, registeredUseCases$ }: Props) => {
<>
<EuiFlexItem grow={false}>
<EuiIcon
size="l"
size="xl"
data-test-subj={`current-workspace-icon-${getUseCase(currentWorkspace)?.icon}`}
type={getUseCase(currentWorkspace)?.icon || 'wsSelector'}
color={getValidWorkspaceColor(currentWorkspace.color)}
/>
</EuiFlexItem>
<EuiFlexItem grow={false} data-test-subj="workspace-menu-current-workspace-name">
<EuiToolTip
anchorClassName="eui-textTruncate"
position="right"
content={currentWorkspaceName}
>
<EuiText size="s" style={{ maxWidth: '195px' }} className="eui-textTruncate">
{currentWorkspaceName}
</EuiText>
</EuiToolTip>
</EuiFlexItem>
<EuiFlexItem grow={false} data-test-subj="workspace-menu-current-use-case">
<EuiText size="s">{getUseCase(currentWorkspace)?.title ?? ''}</EuiText>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiSmallButton
color="text"
onClick={() => {
closePopover();
navigateToWorkspaceDetail(coreStart, currentWorkspace.id);
}}
<EuiFlexItem
grow={false}
data-test-subj="workspace-menu-current-workspace-name"
style={{ maxWidth: '200px' }}
>
<EuiText textAlign="center">{currentWorkspaceName}</EuiText>
<EuiText
size="xs"
data-test-subj="workspace-menu-current-use-case"
textAlign="center"
color="subdued"
>
{manageWorkspaceButton}
</EuiSmallButton>
{getUseCase(currentWorkspace)?.title ?? ''}
</EuiText>
</EuiFlexItem>
</>
) : (
<>
<EuiFlexItem grow={false}>
<EuiIcon size="l" type="wsSelector" />
<EuiIcon size="xl" color="subdued" type="wsSelector" />
</EuiFlexItem>
<EuiFlexItem grow={false} data-test-subj="workspace-menu-current-workspace-name">
{currentWorkspaceName}
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiSmallButton
color="text"
onClick={() => {
closePopover();
coreStart.application.navigateToApp(WORKSPACE_LIST_APP_ID);
}}
>
{manageWorkspacesButton}
</EuiSmallButton>
<EuiText textAlign="center">{currentWorkspaceName}</EuiText>
</EuiFlexItem>
</>
)}
</EuiFlexGroup>
</EuiPanel>
<EuiPanel paddingSize="none" hasBorder={false} color="transparent">

<EuiPanel
paddingSize="s"
hasBorder={false}
color="transparent"
style={{ height: '30vh' }}
className="eui-fullHeight"
>
<WorkspacePickerContent
coreStart={coreStart}
registeredUseCases$={registeredUseCases$}
onClickWorkspace={() => setPopover(false)}
/>
</EuiPanel>
<EuiPanel paddingSize="s" hasBorder={false} color="transparent">
<EuiFlexGroup alignItems="center" justifyContent="spaceBetween" gutterSize="s">
<EuiFlexItem grow={false}>
<EuiSmallButtonEmpty
flush="left"
key={WORKSPACE_LIST_APP_ID}
data-test-subj="workspace-menu-view-all-button"
onClick={() => {
closePopover();
coreStart.application.navigateToApp(WORKSPACE_LIST_APP_ID);
}}
>
{viewAllButton}
</EuiSmallButtonEmpty>
</EuiFlexItem>
{isDashboardAdmin && (

{isDashboardAdmin && (
<EuiPanel paddingSize="s" hasBorder={false} color="transparent">
<EuiHorizontalRule />
<EuiFlexGroup alignItems="center" justifyContent="spaceBetween" gutterSize="s">
<EuiFlexItem>
<EuiButtonEmpty
color="primary"
size="xs"
data-test-subj="workspace-menu-manage-button"
onClick={() => {
closePopover();
coreStart.application.navigateToApp(WORKSPACE_LIST_APP_ID);
}}
>
<EuiText size="s">{manageWorkspacesButton}</EuiText>
</EuiButtonEmpty>
</EuiFlexItem>

<EuiFlexItem grow={false}>
<EuiSmallButton
color="text"
<EuiButton
color="primary"
iconType="plus"
size="s"
key={WORKSPACE_CREATE_APP_ID}
data-test-subj="workspace-menu-create-workspace-button"
onClick={() => {
closePopover();
coreStart.application.navigateToApp(WORKSPACE_CREATE_APP_ID);
}}
>
{createWorkspaceButton}
</EuiSmallButton>
<EuiText size="s">{createWorkspaceButton}</EuiText>
</EuiButton>
</EuiFlexItem>
)}
</EuiFlexGroup>
</EuiPanel>
</EuiFlexGroup>
</EuiPanel>
)}
</EuiPopover>
);
};
Loading

0 comments on commit a05c4a2

Please sign in to comment.