Skip to content

Commit 52e3800

Browse files
opensearch-trigger-bot[bot]github-actions[bot]opensearch-changeset-bot[bot]ruanyl
authored
[Workspace] search use case overview page (opensearch-project#7877) (opensearch-project#7988) (opensearch-project#8046)
* search overview * add unit test for search use case overview page * Changeset file for PR opensearch-project#7877 created/updated * fix merge issue * udpate breadcrumbs for workspace overview page * fix failed ut * fix merge issue * fix ut --------- (cherry picked from commit 9697f33) (cherry picked from commit 3d7b9ed) Signed-off-by: Hailong Cui <[email protected]> Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: opensearch-changeset-bot[bot] <154024398+opensearch-changeset-bot[bot]@users.noreply.github.com> Co-authored-by: Yulong Ruan <[email protected]>
1 parent d6a9aa5 commit 52e3800

File tree

17 files changed

+664
-29
lines changed

17 files changed

+664
-29
lines changed

changelogs/fragments/7877.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
feat:
2+
- [Workspace] Add search use case overview page ([#7877](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/7877))

src/plugins/content_management/public/components/card_container/card_list.test.tsx

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ test('render list of cards', () => {
2020
jest
2121
.spyOn(embeddableStart, 'EmbeddablePanel')
2222
.mockImplementation(() => <span>CardEmbeddablePanel</span>);
23-
render(
23+
const { container, queryAllByText } = render(
2424
<CardList
2525
embeddableServices={embeddableStart}
2626
embeddable={
@@ -37,5 +37,37 @@ test('render list of cards', () => {
3737
}
3838
/>
3939
);
40-
expect(screen.queryAllByText('CardEmbeddablePanel')).toHaveLength(2);
40+
expect(queryAllByText('CardEmbeddablePanel')).toHaveLength(2);
41+
// verify container has div with class euiFlexGroup
42+
expect(container.querySelector('.euiFlexGroup')).toBeInTheDocument();
43+
});
44+
45+
test('render list of cards with grid', () => {
46+
const embeddableStart = embeddablePluginMock.createStartContract();
47+
jest
48+
.spyOn(embeddableStart, 'EmbeddablePanel')
49+
.mockImplementation(() => <span>CardEmbeddablePanel</span>);
50+
const { container } = render(
51+
<CardList
52+
embeddableServices={embeddableStart}
53+
embeddable={
54+
new CardContainer(
55+
{
56+
id: 'card',
57+
panels: {
58+
'card-id-1': { type: CARD_EMBEDDABLE, explicitInput: { id: 'card-id-1' } },
59+
'card-id-2': { type: CARD_EMBEDDABLE, explicitInput: { id: 'card-id-2' } },
60+
'card-id-3': { type: CARD_EMBEDDABLE, explicitInput: { id: 'card-id-3' } },
61+
'card-id-4': { type: CARD_EMBEDDABLE, explicitInput: { id: 'card-id-4' } },
62+
},
63+
grid: true,
64+
columns: 2,
65+
},
66+
embeddableStart
67+
)
68+
}
69+
/>
70+
);
71+
// verify container has div with class euiFlexGrid
72+
expect(container.querySelector('.euiFlexGrid')).toBeInTheDocument();
4173
});

src/plugins/content_management/public/components/card_container/card_list.tsx

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44
*/
55

66
import React from 'react';
7-
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
7+
import { EuiFlexGrid, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
88

9+
import { FlexGridColumns } from '@elastic/eui/src/components/flex/flex_grid';
910
import {
1011
IContainer,
1112
withEmbeddableSubscription,
@@ -22,13 +23,18 @@ interface Props {
2223
}
2324

2425
const CardListInner = ({ embeddable, input, embeddableServices }: Props) => {
25-
if (input.columns) {
26+
if (input.columns && !input.grid) {
2627
const width = `${(1 / input.columns) * 100}%`;
2728
const cards = Object.values(input.panels).map((panel) => {
2829
const child = embeddable.getChild(panel.explicitInput.id);
2930
return (
3031
<EuiFlexItem key={panel.explicitInput.id} style={{ minWidth: `calc(${width} - 8px)` }}>
31-
<embeddableServices.EmbeddablePanel embeddable={child} />
32+
<embeddableServices.EmbeddablePanel
33+
embeddable={child}
34+
hideHeader
35+
hasBorder={false}
36+
hasShadow={false}
37+
/>
3238
</EuiFlexItem>
3339
);
3440
});
@@ -57,6 +63,14 @@ const CardListInner = ({ embeddable, input, embeddableServices }: Props) => {
5763
);
5864
});
5965

66+
if (input.grid && input.columns) {
67+
return (
68+
<EuiFlexGrid columns={input.columns as FlexGridColumns} gutterSize="s">
69+
{cards}
70+
</EuiFlexGrid>
71+
);
72+
}
73+
6074
return (
6175
<EuiFlexGroup wrap={input.wrap} gutterSize="s">
6276
{cards}

src/plugins/content_management/public/components/card_container/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export interface CardExplicitInput {
2020
export type CardContainerInput = ContainerInput<CardExplicitInput> & {
2121
columns?: number;
2222
wrap?: boolean;
23+
grid?: boolean;
2324
};
2425

2526
/**

src/plugins/content_management/public/components/section_input.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ export const createCardInput = (
3535
viewMode: ViewMode.VIEW,
3636
columns: section.columns,
3737
wrap: section.wrap,
38+
grid: section.grid,
3839
panels,
3940
...section.input,
4041
};

src/plugins/content_management/public/services/content_management/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export type Section =
3939
input?: CardContainerExplicitInput;
4040
columns?: number;
4141
wrap?: boolean;
42+
grid?: boolean;
4243
};
4344

4445
export type Content =

src/plugins/home/public/application/application.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ import { HomeApp, ImportSampleDataApp } from './components/home_app';
3838
import { getServices } from './opensearch_dashboards_services';
3939

4040
import './index.scss';
41+
import { ContentManagementPluginStart } from '../../../../plugins/content_management/public';
42+
import { SearchUseCaseOverviewApp } from './components/usecase_overview/search_use_case_app';
4143

4244
export const renderApp = async (
4345
element: HTMLElement,
@@ -90,3 +92,20 @@ export const renderImportSampleDataApp = async (element: HTMLElement, coreStart:
9092
unmountComponentAtNode(element);
9193
};
9294
};
95+
96+
export const renderSearchUseCaseOverviewApp = async (
97+
element: HTMLElement,
98+
coreStart: CoreStart,
99+
contentManagementStart: ContentManagementPluginStart
100+
) => {
101+
render(
102+
<OpenSearchDashboardsContextProvider services={{ ...coreStart }}>
103+
<SearchUseCaseOverviewApp contentManagement={contentManagementStart} />
104+
</OpenSearchDashboardsContextProvider>,
105+
element
106+
);
107+
108+
return () => {
109+
unmountComponentAtNode(element);
110+
};
111+
};

src/plugins/home/public/application/components/sample_data/sample_data_card.test.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ describe('Sample data card', () => {
1919
it('should call the getTargetArea function with the correct arguments', () => {
2020
registerSampleDataCard(contentManagement, coreStart);
2121
const call = registerContentProviderMock.mock.calls[0];
22-
expect(call[0].getTargetArea()).toEqual(['essentials_overview/get_started']);
22+
expect(call[0].getTargetArea()).toEqual('essentials_overview/get_started');
2323
expect(call[0].getContent()).toMatchInlineSnapshot(`
2424
Object {
2525
"cardProps": Object {
@@ -39,5 +39,10 @@ describe('Sample data card', () => {
3939
"title": "Try openSearch",
4040
}
4141
`);
42+
43+
// search use case overview
44+
expect(registerContentProviderMock.mock.calls[1][0].getTargetArea()).toEqual(
45+
'search_overview/get_started'
46+
);
4247
});
4348
});

src/plugins/home/public/application/components/sample_data/sample_data_card.tsx

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,23 @@ import { EuiI18n } from '@elastic/eui';
99
import { i18n } from '@osd/i18n';
1010
import {
1111
ContentManagementPluginStart,
12+
ContentProvider,
1213
ESSENTIAL_OVERVIEW_CONTENT_AREAS,
14+
SEARCH_OVERVIEW_CONTENT_AREAS,
1315
} from '../../../../../content_management/public';
1416
import { IMPORT_SAMPLE_DATA_APP_ID } from '../../../../common/constants';
1517

1618
export const registerSampleDataCard = (
1719
contentManagement: ContentManagementPluginStart,
1820
core: CoreStart
1921
) => {
20-
contentManagement.registerContentProvider({
21-
id: `get_start_sample_data`,
22-
getTargetArea: () => [ESSENTIAL_OVERVIEW_CONTENT_AREAS.GET_STARTED],
22+
const sampleDataCard = (order: number, targetArea: string): ContentProvider => ({
23+
id: `get_start_sample_data_${targetArea}`,
24+
getTargetArea: () => targetArea,
2325
getContent: () => ({
2426
id: 'sample_data',
2527
kind: 'card',
26-
order: 0,
28+
order,
2729
description: i18n.translate('home.sampleData.card.description', {
2830
defaultMessage: 'You can install sample data to experiment with OpenSearch Dashboards.',
2931
}),
@@ -42,4 +44,11 @@ export const registerSampleDataCard = (
4244
},
4345
}),
4446
});
47+
48+
contentManagement.registerContentProvider(
49+
sampleDataCard(0, ESSENTIAL_OVERVIEW_CONTENT_AREAS.GET_STARTED)
50+
);
51+
contentManagement.registerContentProvider(
52+
sampleDataCard(30, SEARCH_OVERVIEW_CONTENT_AREAS.GET_STARTED)
53+
);
4554
};
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* Copyright OpenSearch Contributors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
import { render } from '@testing-library/react';
7+
import React from 'react';
8+
import { coreMock } from '../../../../../../core/public/mocks';
9+
import { OpenSearchDashboardsContextProvider } from '../../../../../opensearch_dashboards_react/public';
10+
import { contentManagementPluginMocks } from '../../../../../content_management/public/mocks';
11+
import { SearchUseCaseOverviewApp } from './search_use_case_app';
12+
import { ContentManagementPluginStart } from '../../../../../content_management/public';
13+
import { BehaviorSubject } from 'rxjs';
14+
import { WorkspaceObject } from 'opensearch-dashboards/public';
15+
16+
describe('<SearchUseCaseOverviewApp />', () => {
17+
const renderPageMock = jest.fn();
18+
renderPageMock.mockReturnValue('dummy page');
19+
const mock = {
20+
...contentManagementPluginMocks.createStartContract(),
21+
renderPage: renderPageMock,
22+
};
23+
const coreStartMocks = coreMock.createStart();
24+
25+
function renderSearchUseCaseOverviewApp(
26+
contentManagement: ContentManagementPluginStart,
27+
services = { ...coreStartMocks }
28+
) {
29+
return (
30+
<OpenSearchDashboardsContextProvider services={services}>
31+
<SearchUseCaseOverviewApp contentManagement={contentManagement} />
32+
</OpenSearchDashboardsContextProvider>
33+
);
34+
}
35+
36+
beforeEach(() => {
37+
jest.clearAllMocks();
38+
});
39+
40+
it('render for workspace disabled case', () => {
41+
const { container } = render(renderSearchUseCaseOverviewApp(mock, coreStartMocks));
42+
43+
expect(container).toMatchInlineSnapshot(`
44+
<div>
45+
dummy page
46+
</div>
47+
`);
48+
49+
expect(coreStartMocks.chrome.setBreadcrumbs).toHaveBeenCalledWith([
50+
{ text: 'Search overview' },
51+
]);
52+
expect(mock.renderPage).toBeCalledWith('search_overview');
53+
});
54+
55+
it('render for workspace enabled case', () => {
56+
const coreStartMocksWithWorkspace = {
57+
...coreStartMocks,
58+
workspaces: {
59+
...coreStartMocks.workspaces,
60+
currentWorkspace$: new BehaviorSubject({
61+
id: 'foo',
62+
name: 'foo ws',
63+
}),
64+
},
65+
};
66+
67+
const { container } = render(renderSearchUseCaseOverviewApp(mock, coreStartMocksWithWorkspace));
68+
69+
expect(container).toMatchInlineSnapshot(`
70+
<div>
71+
dummy page
72+
</div>
73+
`);
74+
75+
expect(coreStartMocks.chrome.setBreadcrumbs).toHaveBeenCalledWith([{ text: 'foo ws' }]);
76+
expect(mock.renderPage).toBeCalledWith('search_overview');
77+
});
78+
});

0 commit comments

Comments
 (0)