diff --git a/changelogs/fragments/8614.yml b/changelogs/fragments/8614.yml new file mode 100644 index 000000000000..0f57ef1e86ca --- /dev/null +++ b/changelogs/fragments/8614.yml @@ -0,0 +1,2 @@ +fix: +- Update content and styling of use case getting started cards ([#8614](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/8614)) \ No newline at end of file diff --git a/src/plugins/home/public/application/components/sample_data/sample_data_card.test.tsx b/src/plugins/home/public/application/components/sample_data/sample_data_card.test.tsx index 6d3d3559605c..677f87df8718 100644 --- a/src/plugins/home/public/application/components/sample_data/sample_data_card.test.tsx +++ b/src/plugins/home/public/application/components/sample_data/sample_data_card.test.tsx @@ -23,28 +23,17 @@ describe('Sample data card', () => { expect(call[0].getContent()).toMatchInlineSnapshot(` Object { "cardProps": Object { - "selectable": Object { - "children": , - "isSelected": false, - "onClick": [Function], - }, - "titleElement": "h4", - "titleSize": "s", + "className": "usecaseOverviewGettingStartedCard", }, - "description": "Explore sample data before adding your own.", + "description": "Install sample data to experiment with OpenSearch.", + "getFooter": [Function], + "getIcon": [Function], "id": "sample_data", "kind": "card", + "onClick": [Function], "order": 0, - "title": "Try OpenSearch", + "title": "", } `); - - // search use case overview - expect(registerContentProviderMock.mock.calls[1][0].getTargetArea()).toEqual( - 'search_overview/get_started' - ); }); }); diff --git a/src/plugins/home/public/application/components/sample_data/sample_data_card.tsx b/src/plugins/home/public/application/components/sample_data/sample_data_card.tsx index 061f00335212..30d1c64c8798 100644 --- a/src/plugins/home/public/application/components/sample_data/sample_data_card.tsx +++ b/src/plugins/home/public/application/components/sample_data/sample_data_card.tsx @@ -5,13 +5,12 @@ import { CoreStart } from 'opensearch-dashboards/public'; import React from 'react'; -import { EuiI18n } from '@elastic/eui'; +import { EuiI18n, EuiIcon, EuiTextColor } from '@elastic/eui'; import { i18n } from '@osd/i18n'; import { ContentManagementPluginStart, ContentProvider, ESSENTIAL_OVERVIEW_CONTENT_AREAS, - SEARCH_OVERVIEW_CONTENT_AREAS, } from '../../../../../content_management/public'; import { IMPORT_SAMPLE_DATA_APP_ID } from '../../../../common/constants'; @@ -27,22 +26,21 @@ export const registerSampleDataCard = ( kind: 'card', order, description: i18n.translate('home.sampleData.card.description', { - defaultMessage: 'Explore sample data before adding your own.', - }), - title: i18n.translate('home.sampleData.card.title', { - defaultMessage: 'Try OpenSearch', + defaultMessage: 'Install sample data to experiment with OpenSearch.', }), + title: '', + onClick: () => { + // TODO change to a modal + core.application.navigateToApp(IMPORT_SAMPLE_DATA_APP_ID); + }, + getIcon: () => , + getFooter: () => ( + + + + ), cardProps: { - titleElement: 'h4', - titleSize: 's', - selectable: { - children: , - isSelected: false, - onClick: () => { - // TODO change to a modal - core.application.navigateToApp(IMPORT_SAMPLE_DATA_APP_ID); - }, - }, + className: 'usecaseOverviewGettingStartedCard', }, }), }); @@ -50,7 +48,4 @@ export const registerSampleDataCard = ( contentManagement.registerContentProvider( sampleDataCard(0, ESSENTIAL_OVERVIEW_CONTENT_AREAS.GET_STARTED) ); - contentManagement.registerContentProvider( - sampleDataCard(30, SEARCH_OVERVIEW_CONTENT_AREAS.GET_STARTED) - ); }; diff --git a/src/plugins/home/public/application/components/usecase_overview/search_use_case_setup.test.tsx b/src/plugins/home/public/application/components/usecase_overview/search_use_case_setup.test.tsx index 9c5efee630c1..4b64c4d7532e 100644 --- a/src/plugins/home/public/application/components/usecase_overview/search_use_case_setup.test.tsx +++ b/src/plugins/home/public/application/components/usecase_overview/search_use_case_setup.test.tsx @@ -67,52 +67,35 @@ describe('Search use case setup', () => { expect(call[0].getContent()).toMatchInlineSnapshot(` Object { "cardProps": Object { - "selectable": Object { - "children": , - "isSelected": false, - "onClick": [Function], - }, - "titleElement": "h4", - "titleSize": "s", + "className": "usecaseOverviewGettingStartedCard", }, - "description": "You can run a search using REST API or language client. For experimentation, you can also run queries interactively.", + "description": "Explore search capabilities and functionality of OpenSearch.", + "getFooter": [Function], + "getIcon": [Function], "id": "access_search_functionality", "kind": "card", + "onClick": [Function], "order": 10, - "title": "Access search functionality", + "title": "", } `); // search type section const searchTypesCall = registerContentProviderMock.mock.calls[2]; - expect(searchTypesCall[0].getTargetArea()).toEqual('search_overview/different_search_types'); + expect(searchTypesCall[0].getTargetArea()).toEqual('search_overview/get_started'); expect(searchTypesCall[0].getContent()).toMatchInlineSnapshot(` Object { "cardProps": Object { - "children":
- - View Documentation - -
, - "layout": "horizontal", - "titleElement": "h3", - "titleSize": "s", + "className": "usecaseOverviewGettingStartedCard", }, - "description": "Lexical or keyword search matches documents based on exact words or phrases. Search the text using human-friendly query string query syntax or create complex, customizable queries using Query DSL—the OpenSearch query language.", + "description": "Explore data to uncover and discover insights.", + "getFooter": [Function], "getIcon": [Function], - "id": "text_search", + "id": "get_start_discover", "kind": "card", - "order": 10, - "title": "Text search", + "onClick": [Function], + "order": 30, + "title": "", } `); }); diff --git a/src/plugins/home/public/application/components/usecase_overview/search_use_case_setup.tsx b/src/plugins/home/public/application/components/usecase_overview/search_use_case_setup.tsx index 96e0b159c595..b8c5102d9ccd 100644 --- a/src/plugins/home/public/application/components/usecase_overview/search_use_case_setup.tsx +++ b/src/plugins/home/public/application/components/usecase_overview/search_use_case_setup.tsx @@ -5,7 +5,7 @@ import React from 'react'; import { CoreStart } from 'opensearch-dashboards/public'; -import { EuiI18n, EuiIcon, EuiLink } from '@elastic/eui'; +import { EuiI18n, EuiIcon, EuiLink, EuiTextColor } from '@elastic/eui'; import { i18n } from '@osd/i18n'; import { ContentManagementPluginSetup, @@ -15,6 +15,8 @@ import { SEARCH_OVERVIEW_CONTENT_AREAS, } from '../../../../../content_management/public'; +const DISCOVER_APP_ID = 'discover'; + export const setupSearchUseCase = (contentManagement: ContentManagementPluginSetup) => { contentManagement.registerPage({ id: SEARCH_OVERVIEW_PAGE_ID, @@ -56,39 +58,64 @@ export const registerContentToSearchUseCasePage = ( contentManagement: ContentManagementPluginStart, core: CoreStart ) => { + // Replicate external EuiLink icon as doc links can't use EuiLink for visual consistency + const externalLinkIcon = ( + <> + {' '} + + + ); const getStartedCards = [ { id: 'access_search_functionality', order: 10, - title: i18n.translate('home.searchOverview.setup.accessSearch.title', { - defaultMessage: 'Access search functionality', - }), + icon: , + title: '', description: i18n.translate('home.searchOverview.setup.accessSearch.description', { - defaultMessage: - 'You can run a search using REST API or language client. For experimentation, you can also run queries interactively.', + defaultMessage: 'Explore search capabilities and functionality of OpenSearch.', }), footer: ( - + + + {externalLinkIcon} + ), documentURL: 'https://opensearch.org/docs/latest/search-plugins/', }, { id: 'create_document_index', order: 20, - title: i18n.translate('home.searchOverview.setup.createDocumentIndex.title', { - defaultMessage: 'Create a document index', - }), + icon: , + title: '', description: i18n.translate('home.searchOverview.setup.createDocumentIndex.description', { - defaultMessage: - 'You can create a document collection (an index) by adding documents to a new index.', + defaultMessage: 'Create a document collection (an index) to query your data.', + }), + footer: ( + + + {externalLinkIcon} + + ), + documentURL: 'https://opensearch.org/docs/latest/getting-started/intro/', + }, + { + id: 'get_start_discover', + order: 30, + icon: , + title: '', + description: i18n.translate('home.searchOverview.setup.discover.description', { + defaultMessage: 'Explore data to uncover and discover insights.', }), footer: ( - + + + ), documentURL: 'https://opensearch.org/docs/latest/getting-started/intro/', + navigateAppId: DISCOVER_APP_ID, }, ]; @@ -101,16 +128,17 @@ export const registerContentToSearchUseCasePage = ( order: card.order, title: card.title, description: card.description, + onClick: () => { + if (card.navigateAppId) { + core.application.navigateToApp(card.navigateAppId); + } else { + window.open(card.documentURL, '_blank'); + } + }, + getFooter: () => card.footer, + getIcon: () => card.icon, cardProps: { - titleElement: 'h4', - titleSize: 's', - selectable: { - onClick: () => { - window.open(card.documentURL, '_blank'); - }, - children: card.footer, - isSelected: false, - }, + className: 'usecaseOverviewGettingStartedCard', }, }), getTargetArea: () => SEARCH_OVERVIEW_CONTENT_AREAS.GET_STARTED, diff --git a/src/plugins/workspace/public/components/use_case_overview/get_started_cards.tsx b/src/plugins/workspace/public/components/use_case_overview/get_started_cards.tsx index f9ff96efd0f0..a4a880cd45fe 100644 --- a/src/plugins/workspace/public/components/use_case_overview/get_started_cards.tsx +++ b/src/plugins/workspace/public/components/use_case_overview/get_started_cards.tsx @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { EuiI18n } from '@elastic/eui'; +import { EuiI18n, EuiIcon, EuiTextColor } from '@elastic/eui'; import { i18n } from '@osd/i18n'; import React from 'react'; @@ -11,6 +11,7 @@ interface GetStartCard { id: string; title: string; description: string; + icon: React.JSX.Element; footer: React.JSX.Element; navigateAppId: string; order: number; @@ -23,43 +24,48 @@ const DASHBOARDS_APP_ID = 'dashboards'; export const getStartedCards: GetStartCard[] = [ { id: 'get_start_discover', - title: i18n.translate('workspace.essential_overview.discover.card.title', { - defaultMessage: 'Explore data', - }), + icon: , + title: '', description: i18n.translate('workspace.essential_overview.discover.card.description', { - defaultMessage: 'Explore data to uncover insights.', + defaultMessage: 'Explore data to uncover and discover insights.', }), footer: ( - + + + ), navigateAppId: DISCOVER_APP_ID, order: 20, }, { id: 'get_start_visualization', - title: i18n.translate('workspace.essential_overview.visualize.card.title', { - defaultMessage: 'Visualize data', - }), + icon: , + title: '', description: i18n.translate('workspace.essential_overview.visualize.card.description', { defaultMessage: 'Gain deeper insights by visualizing and aggregating your data.', }), footer: ( - + + + ), navigateAppId: VISUALIZE_APP_ID, order: 30, }, { id: 'get_start_dashboards', - title: i18n.translate('workspace.essential_overview.dashboards.card.title', { - defaultMessage: 'Explore your data at a glance', - }), + icon: , + title: '', description: i18n.translate('workspace.essential_overview.dashboards.card.description', { - defaultMessage: - 'Monitor and understand your data connections using dynamic data visualization tools.', + defaultMessage: 'Monitor and explore your data using dynamic data visualization tools.', }), footer: ( - + + + ), navigateAppId: DASHBOARDS_APP_ID, order: 40, diff --git a/src/plugins/workspace/public/components/use_case_overview/setup_overview.scss b/src/plugins/workspace/public/components/use_case_overview/setup_overview.scss index 607b5eef6863..b17f2136af5c 100644 --- a/src/plugins/workspace/public/components/use_case_overview/setup_overview.scss +++ b/src/plugins/workspace/public/components/use_case_overview/setup_overview.scss @@ -1,3 +1,24 @@ -.analyticsGettingStartedWorkspaceCardsIcon { - color: $euiColorMediumShade; +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +.usecaseOverviewGettingStartedCard { + // Hide titles as they take up space even when empty + // stylelint-disable-next-line @osd/stylelint/no_modifying_global_selectors + .euiCard__title { + display: none; + } + + // Remove margins from description as titles are hidden and icons as they're at the top + // stylelint-disable-next-line @osd/stylelint/no_modifying_global_selectors + .euiCard__description, + .euiCard__icon { + margin-top: 0; + } + + // stylelint-disable-next-line @osd/stylelint/no_modifying_global_selectors + .euiCard__footer { + margin-top: $euiSizeS; + } } diff --git a/src/plugins/workspace/public/components/use_case_overview/setup_overview.test.tsx b/src/plugins/workspace/public/components/use_case_overview/setup_overview.test.tsx index ea0a12b930cf..7b6fa9b13e33 100644 --- a/src/plugins/workspace/public/components/use_case_overview/setup_overview.test.tsx +++ b/src/plugins/workspace/public/components/use_case_overview/setup_overview.test.tsx @@ -75,22 +75,16 @@ describe('Setup use case overview', () => { expect(firstCall[0].getContent()).toMatchInlineSnapshot(` Object { "cardProps": Object { - "selectable": Object { - "children": , - "isSelected": false, - "onClick": [Function], - }, - "titleElement": "h4", - "titleSize": "s", + "className": "usecaseOverviewGettingStartedCard", }, - "description": "Explore data to uncover insights.", + "description": "Explore data to uncover and discover insights.", + "getFooter": [Function], + "getIcon": [Function], "id": "get_start_discover", "kind": "card", + "onClick": [Function], "order": 20, - "title": "Explore data", + "title": "", } `); }); @@ -137,17 +131,16 @@ describe('Setup use case overview', () => { expect(firstCall[0].getContent()).toMatchInlineSnapshot(` Object { "cardProps": Object { - "layout": "horizontal", - "titleElement": "h4", - "titleSize": "s", + "className": "usecaseOverviewGettingStartedCard", }, "description": "Gain visibility into system health, performance, and reliability through monitoring of logs, metrics and traces.", + "getFooter": [Function], "getIcon": [Function], "id": "observability", "kind": "card", "onClick": [Function], "order": 4000, - "title": "Observability", + "title": "", } `); }); diff --git a/src/plugins/workspace/public/components/use_case_overview/setup_overview.tsx b/src/plugins/workspace/public/components/use_case_overview/setup_overview.tsx index 5688e1108c31..4cb4859c40e4 100644 --- a/src/plugins/workspace/public/components/use_case_overview/setup_overview.tsx +++ b/src/plugins/workspace/public/components/use_case_overview/setup_overview.tsx @@ -5,7 +5,7 @@ import React from 'react'; import { CoreStart } from 'opensearch-dashboards/public'; -import { EuiIcon } from '@elastic/eui'; +import { EuiIcon, EuiTextColor } from '@elastic/eui'; import { first } from 'rxjs/operators'; import { ContentManagementPluginSetup, @@ -76,16 +76,13 @@ export const registerEssentialOverviewContent = ( order: card.order, description: card.description, title: card.title, + onClick: () => { + core.application.navigateToApp(card.navigateAppId); + }, + getFooter: () => card.footer, + getIcon: () => card.icon, cardProps: { - titleElement: 'h4', - titleSize: 's', - selectable: { - onClick: () => { - core.application.navigateToApp(card.navigateAppId); - }, - children: card.footer, - isSelected: false, - }, + className: 'usecaseOverviewGettingStartedCard', }, }), }); @@ -135,19 +132,13 @@ export const registerAnalyticsAllOverviewContent = ( getContent: () => ({ id: card.id, kind: 'card', - getIcon: () => - React.createElement(EuiIcon, { - size: 'xl', - type: card.icon || 'wsSelector', - className: 'analyticsGettingStartedWorkspaceCardsIcon', - }), + getIcon: () => , order: card.order || index, description: card.description, - title: card.title, + title: '', + getFooter: () => {card.title}, cardProps: { - titleElement: 'h4', - titleSize: 's', - layout: 'horizontal', + className: 'usecaseOverviewGettingStartedCard', }, onClick: async () => { const navGroups = await core.chrome.navGroup.getNavGroupsMap$().pipe(first()).toPromise();