Skip to content

Commit

Permalink
click on workspace name navigates to use case overview page
Browse files Browse the repository at this point in the history
Signed-off-by: Hailong Cui <[email protected]>
  • Loading branch information
Hailong-am committed Aug 19, 2024
1 parent 0525ec8 commit 99f6caa
Show file tree
Hide file tree
Showing 5 changed files with 169 additions and 77 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,40 @@ import { coreMock } from '../../../../../core/public/mocks';
import { fireEvent, render, waitFor } from '@testing-library/react';
import { WorkspaceListCard } from './workspace_list_card';
import { recentWorkspaceManager } from '../../recent_workspace_manager';
import { BehaviorSubject } from 'rxjs';
import { NavGroupItemInMap } from 'opensearch-dashboards/public';

describe('workspace list card render normally', () => {
const coreStart = coreMock.createStart();
const navGroupMap: Record<string, NavGroupItemInMap> = {
group1: {
id: 'group1',
title: 'title',
description: 'desc',
navLinks: [
{
id: 'link1',
},
],
},
};
const coreStart = {
...coreMock.createStart(),
chrome: {
...coreMock.createStart().chrome,
navGroup: {
...coreMock.createStart().chrome.navGroup,
getNavGroupsMap$: () => new BehaviorSubject(navGroupMap),
},
},
};

beforeAll(() => {
const workspaceList = [
{
id: 'ws-1',
name: 'foo',
lastUpdatedTime: new Date().toISOString(),
features: ['use-case-group1'],
},
{
id: 'ws-2',
Expand All @@ -38,7 +62,11 @@ describe('workspace list card render normally', () => {
expect(getByTestId('workspace_filter')).toHaveDisplayValue('Recently viewed');

// empty statue for recently viewed
expect(getByText('Workspaces you have recently viewed will appear here.')).toBeInTheDocument();
expect(
getByText(
'Contact your administrator to create a workspace or to be added to an existing one.'
)
).toBeInTheDocument();
});

it('should show default filter as recently viewed', () => {
Expand All @@ -64,6 +92,21 @@ describe('workspace list card render normally', () => {
expect(getByText('bar')).toBeInTheDocument();
});

it('should navigate to workspace use case overview page when click on workspace name', () => {
const { getByTestId, getByText } = render(<WorkspaceListCard core={coreStart} />);
const filterSelector = getByTestId('workspace_filter');
fireEvent.change(filterSelector, { target: { value: 'updated' } });
expect(getByTestId('workspace_filter')).toHaveDisplayValue('Recently updated');

// workspace list
expect(getByText('foo')).toBeInTheDocument();

fireEvent.click(getByText('foo'));
expect(coreStart.application.getUrlForApp).toHaveBeenLastCalledWith('link1', {
absolute: true,
});
});

it('should render create workspace button when is dashboard admin and navigate to create new workspace page when clicking on plus button', () => {
coreStart.application.capabilities = {
...coreStart.application.capabilities,
Expand All @@ -79,7 +122,10 @@ describe('workspace list card render normally', () => {
});

it('should navigate to workspace list page when click on View all button', () => {
const { getByText } = render(<WorkspaceListCard core={coreStart} />);
const { getByText, getByTestId } = render(<WorkspaceListCard core={coreStart} />);
const filterSelector = getByTestId('workspace_filter');
fireEvent.change(filterSelector, { target: { value: 'updated' } });
expect(getByTestId('workspace_filter')).toHaveDisplayValue('Recently updated');
const mockButton = getByText('View all');
fireEvent.click(mockButton);
expect(coreStart.application.navigateToApp).toHaveBeenCalledWith('workspace_list');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,29 +10,28 @@ import {
EuiDescriptionList,
EuiIcon,
EuiFlexItem,
EuiSelect,
EuiButtonIcon,
EuiText,
EuiSpacer,
EuiPanel,
EuiTitle,
EuiToolTip,
EuiEmptyPrompt,
EuiSmallButton,
EuiCompressedSelect,
} from '@elastic/eui';
import { i18n } from '@osd/i18n';
import moment from 'moment';
import { orderBy } from 'lodash';
import { useObservable } from 'react-use';
import { CoreStart, WorkspaceAvailability, WorkspaceObject } from '../../../../../core/public';
import { CoreStart, WorkspaceObject } from '../../../../../core/public';

import { WORKSPACE_CREATE_APP_ID, WORKSPACE_LIST_APP_ID } from '../../../common/constants';
import { recentWorkspaceManager } from '../../recent_workspace_manager';
import { getFirstUseCaseOfFeatureConfigs } from '../../utils';
import { navigateToAppWithinWorkspace } from '../utils/workspace';

const WORKSPACE_LIST_CARD_DESCRIPTION = i18n.translate('workspace.list.card.description', {
defaultMessage:
'Workspaces are dedicated environments for organizing and collaborating on your data, dashboards, and analytics workflows. Each Workspace acts as a self-contained space with its own set of saved objects and access controls.',
defaultMessage: 'Dedicated environments for organizing, sharing and collaborating.',
});

const MAX_ITEM_IN_LIST = 5;
Expand Down Expand Up @@ -78,24 +77,78 @@ export const WorkspaceListCard = (props: WorkspaceListCardProps) => {
return [];
}, [filter, availableWorkspaces]);

const handleSwitchWorkspace = (id: string) => {
const handleSwitchWorkspace = (workspaceId: string) => {
const { application, http } = props.core;
const workspaceObj = availableWorkspaces.find((item) => item.id === id);
const workspaceObj = availableWorkspaces.find((item) => item.id === workspaceId);
const useCase = getFirstUseCaseOfFeatureConfigs(workspaceObj?.features || []);
if (useCase && navGroups) {
// should be workspace use case overview page
const availableLinks = navGroups[useCase].navLinks?.filter(
(navLink) => navLink.workspaceAvailability !== WorkspaceAvailability.outsideWorkspace
);
const appId = availableLinks?.[0].id;
navigateToAppWithinWorkspace({ application, http }, id, appId);
const appId = navGroups[useCase].navLinks?.[0].id;
navigateToAppWithinWorkspace({ application, http }, workspaceId, appId);
}
};

const { application } = props.core;

const isDashboardAdmin = application.capabilities.dashboards?.isDashboardAdmin;

const createWorkspace = i18n.translate('workspace.list.card.createWorkspace', {
defaultMessage: 'Create workspace',
});

const workspaceAvailable = workspaceList && workspaceList.length > 0;

const createWorkspaceButton = (
<EuiSmallButton
iconType="plus"
data-test-subj="create_workspace"
aria-label="create workspace"
onClick={() => {
application.navigateToApp(WORKSPACE_CREATE_APP_ID);
}}
>
{createWorkspace}
</EuiSmallButton>
);

let emptyStateBody: JSX.Element = (
<EuiText color="subdued" size="s">
{i18n.translate('workspace.list.card.empty.readOnly', {
defaultMessage:
'Contact your administrator to create a workspace or to be added to an existing one.',
})}
</EuiText>
);

if (isDashboardAdmin) {
emptyStateBody = (
<>
<EuiText color="subdued" size="s">
{i18n.translate('workspace.list.card.empty', {
defaultMessage: 'Create a workspace to get started.',
})}
</EuiText>
<EuiSpacer size="s" />
<EuiFlexGroup gutterSize="s" justifyContent="spaceBetween" alignItems="center">
<EuiFlexItem>
<EuiLink
onClick={() => {
application.navigateToApp(WORKSPACE_LIST_APP_ID);
}}
>
<EuiText size="s">
{i18n.translate('workspace.list.card.manageWorkspaces', {
defaultMessage: 'Manage workspaces',
})}
</EuiText>
</EuiLink>
</EuiFlexItem>
<EuiFlexItem>{createWorkspaceButton}</EuiFlexItem>
</EuiFlexGroup>
</>
);
}

return (
<EuiPanel paddingSize="s" hasBorder={false} hasShadow={false}>
<EuiFlexGroup
Expand All @@ -117,7 +170,7 @@ export const WorkspaceListCard = (props: WorkspaceListCardProps) => {
</EuiToolTip>
</EuiFlexItem>
<EuiFlexItem grow={5}>
<EuiSelect
<EuiCompressedSelect
value={filter}
data-test-subj="workspace_filter"
onChange={(e) => {
Expand All @@ -139,37 +192,27 @@ export const WorkspaceListCard = (props: WorkspaceListCardProps) => {
]}
/>
</EuiFlexItem>
{isDashboardAdmin && (
<EuiFlexItem grow={false}>
<EuiToolTip position="top" content="Create workspace">
<EuiButtonIcon
data-test-subj="create_workspace"
aria-label="create workspace"
display="base"
iconType="plus"
size="m"
onClick={() => {
application.navigateToApp(WORKSPACE_CREATE_APP_ID);
}}
/>
{isDashboardAdmin && workspaceAvailable && (
<EuiFlexItem grow={true}>
<EuiToolTip position="top" content={createWorkspace}>
{createWorkspaceButton}
</EuiToolTip>
</EuiFlexItem>
)}
</EuiFlexGroup>
</EuiFlexItem>
<EuiSpacer />
<EuiFlexItem grow={true}>
{workspaceList && workspaceList.length === 0 ? (
{!workspaceList || workspaceList.length === 0 ? (
<EuiEmptyPrompt
iconType="database"
iconType="spacesApp"
titleSize="xs"
title={<p>No Workspaces found</p>}
body={i18n.translate('workspace.list.card.empty', {
values: {
filter,
},
defaultMessage: 'Workspaces you have recently {filter} will appear here.',
})}
title={
<EuiTitle size="s">
<EuiText color="subdued">No Workspaces available</EuiText>
</EuiTitle>
}
body={emptyStateBody}
/>
) : (
<EuiDescriptionList
Expand All @@ -196,19 +239,21 @@ export const WorkspaceListCard = (props: WorkspaceListCardProps) => {
)}
</EuiFlexItem>
<EuiSpacer />
<EuiFlexItem grow={false}>
<EuiLink
onClick={() => {
application.navigateToApp(WORKSPACE_LIST_APP_ID);
}}
>
<EuiText size="s">
{i18n.translate('workspace.list.card.view_all', {
defaultMessage: 'View all',
})}
</EuiText>
</EuiLink>
</EuiFlexItem>
{workspaceAvailable && (
<EuiFlexItem grow={false}>
<EuiLink
onClick={() => {
application.navigateToApp(WORKSPACE_LIST_APP_ID);
}}
>
<EuiText size="s">
{i18n.translate('workspace.list.card.view_all', {
defaultMessage: 'View all',
})}
</EuiText>
</EuiLink>
</EuiFlexItem>
)}
</EuiFlexGroup>
</EuiPanel>
);
Expand Down
4 changes: 2 additions & 2 deletions src/plugins/workspace/public/components/utils/workspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ type Core = Pick<CoreStart, 'application' | 'http'>;

export const navigateToWorkspaceDetail = (
{ application, http }: Core,
id: string,
workspaceId: string,
tabId: string = DetailTab.Details
) => {
navigateToAppWithinWorkspace(
{ application, http },
id,
workspaceId,
WORKSPACE_DETAIL_APP_ID,
`/?tab=${tabId}`
);
Expand Down
Loading

0 comments on commit 99f6caa

Please sign in to comment.