diff --git a/src/core/utils/default_nav_groups.ts b/src/core/utils/default_nav_groups.ts
index 7278734ae826..bbd38c81ffc5 100644
--- a/src/core/utils/default_nav_groups.ts
+++ b/src/core/utils/default_nav_groups.ts
@@ -52,8 +52,7 @@ const defaultNavGroups = {
defaultMessage: 'Observability',
}),
description: i18n.translate('core.ui.group.observability.description', {
- defaultMessage:
- 'Gain visibility into system health, performance, and reliability through monitoring and analysis of logs, metrics, and traces.',
+ defaultMessage: 'Gain visibility into your application and infrastructure',
}),
order: 4000,
icon: 'wsObservability',
@@ -64,8 +63,7 @@ const defaultNavGroups = {
defaultMessage: 'Security Analytics',
}),
description: i18n.translate('core.ui.group.security.analytics.description', {
- defaultMessage:
- 'Detect and investigate potential security threats and vulnerabilities across your systems and data.',
+ defaultMessage: 'Enhance your security posture with advanced analytics',
}),
order: 5000,
icon: 'wsSecurityAnalytics',
@@ -88,8 +86,7 @@ const defaultNavGroups = {
defaultMessage: 'Search',
}),
description: i18n.translate('core.ui.group.search.description', {
- defaultMessage:
- "Quickly find and explore relevant information across your organization's data sources.",
+ defaultMessage: 'Discover and query your data with ease',
}),
order: 6000,
icon: 'wsSearch',
diff --git a/src/plugins/home/public/application/components/use_case_card.test.ts b/src/plugins/home/public/application/components/use_case_card.test.ts
new file mode 100644
index 000000000000..e26e6b1fb0eb
--- /dev/null
+++ b/src/plugins/home/public/application/components/use_case_card.test.ts
@@ -0,0 +1,78 @@
+/*
+ * Copyright OpenSearch Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import { EuiIcon } from '@elastic/eui';
+import { coreMock } from '../../../../../core/public/mocks';
+import { registerUseCaseCard } from './use_case_card';
+import { contentManagementPluginMocks } from '../../../../content_management/public';
+
+describe('registerUseCaseCard', () => {
+ const registerContentProviderFn = jest.fn();
+ const contentManagementStartMock = {
+ ...contentManagementPluginMocks.createStartContract(),
+ registerContentProvider: registerContentProviderFn,
+ };
+
+ const core = coreMock.createStart();
+
+ it('should register useCase card correctly', () => {
+ registerUseCaseCard(contentManagementStartMock, core, {
+ id: 'testId',
+ order: 1,
+ target: 'osd_homepage/get_started',
+ icon: 'wsObservability',
+ title: 'observability',
+ description: 'Gain visibility into your application and infrastructure',
+ navigateAppId: 'observability_overview',
+ });
+
+ expect(contentManagementStartMock.registerContentProvider).toHaveBeenCalledTimes(1);
+
+ const registerCall = contentManagementStartMock.registerContentProvider.mock.calls[0][0];
+
+ expect(registerCall.getTargetArea()).toEqual('osd_homepage/get_started');
+
+ expect(registerCall.getContent()).toEqual({
+ id: 'testId',
+ kind: 'card',
+ order: 1,
+ description: 'Gain visibility into your application and infrastructure',
+ title: 'observability',
+ cardProps: {
+ layout: 'horizontal',
+ },
+ onClick: expect.any(Function),
+ getIcon: expect.any(Function),
+ });
+
+ const icon = registerCall.getContent().getIcon();
+ expect(icon.type).toBe(EuiIcon);
+ expect(icon.props).toEqual({
+ size: 'l',
+ color: 'subdued',
+ type: 'wsObservability',
+ });
+ });
+
+ it('should be able to navigate to the expected overview page when click the card', () => {
+ const navigateToAppMock = jest.fn();
+ core.application.navigateToApp = navigateToAppMock;
+
+ registerUseCaseCard(contentManagementStartMock, core, {
+ id: 'testId',
+ order: 1,
+ target: 'osd_homepage/get_started',
+ icon: 'wsObservability',
+ title: 'observability',
+ description: 'Gain visibility into your application and infrastructure',
+ navigateAppId: 'observability_overview',
+ });
+
+ const registerCall = contentManagementStartMock.registerContentProvider.mock.calls[0][0];
+ const card = registerCall.getContent();
+ card.onClick();
+ expect(navigateToAppMock).toHaveBeenCalledWith('observability_overview');
+ });
+});
diff --git a/src/plugins/home/public/application/components/use_case_card.ts b/src/plugins/home/public/application/components/use_case_card.ts
new file mode 100644
index 000000000000..b71f381358f4
--- /dev/null
+++ b/src/plugins/home/public/application/components/use_case_card.ts
@@ -0,0 +1,55 @@
+/*
+ * Copyright OpenSearch Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import React from 'react';
+import { CoreStart } from 'opensearch-dashboards/public';
+import { EuiIcon } from '@elastic/eui';
+import { ContentManagementPluginStart } from '../../../../content_management/public';
+
+export const registerUseCaseCard = (
+ contentManagement: ContentManagementPluginStart,
+ core: CoreStart,
+ {
+ target,
+ order,
+ id,
+ title,
+ description,
+ icon,
+ navigateAppId,
+ }: {
+ target: string;
+ order: number;
+ id: string;
+ title: string;
+ description: string;
+ icon: string;
+ navigateAppId: string;
+ }
+) => {
+ contentManagement.registerContentProvider({
+ id: `home_get_started_${id}`,
+ getTargetArea: () => target,
+ getContent: () => ({
+ id,
+ kind: 'card',
+ order,
+ description,
+ title,
+ cardProps: {
+ layout: 'horizontal',
+ },
+ onClick: () => {
+ core.application.navigateToApp(navigateAppId);
+ },
+ getIcon: () =>
+ React.createElement(EuiIcon, {
+ size: 'l',
+ color: 'subdued',
+ type: icon,
+ }),
+ }),
+ });
+};
diff --git a/src/plugins/home/public/application/home_render.test.tsx b/src/plugins/home/public/application/home_render.test.tsx
new file mode 100644
index 000000000000..34a5d690b44b
--- /dev/null
+++ b/src/plugins/home/public/application/home_render.test.tsx
@@ -0,0 +1,142 @@
+/*
+ * Copyright OpenSearch Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import { DEFAULT_NAV_GROUPS } from '../../../../core/public';
+import {
+ HOME_CONTENT_AREAS,
+ SEARCH_OVERVIEW_PAGE_ID,
+ OBSERVABILITY_OVERVIEW_PAGE_ID,
+ SECURITY_ANALYTICS_OVERVIEW_PAGE_ID,
+} from '../../../../plugins/content_management/public';
+import { contentManagementPluginMocks } from '../../../../plugins/content_management/public/mocks';
+import { registerUseCaseCard } from './components/use_case_card';
+import { initHome } from './home_render';
+
+import {
+ WHATS_NEW_CONFIG,
+ LEARN_OPENSEARCH_CONFIG,
+ registerHomeListCard,
+} from './components/home_list_card';
+
+jest.mock('./components/use_case_card', () => ({
+ registerUseCaseCard: jest.fn(),
+}));
+
+jest.mock('./components/home_list_card', () => ({
+ registerHomeListCard: jest.fn(),
+}));
+
+describe('initHome', () => {
+ const registerContentProviderFn = jest.fn();
+ const contentManagementStartMock = {
+ ...contentManagementPluginMocks.createStartContract(),
+ registerContentProvider: registerContentProviderFn,
+ };
+
+ beforeEach(() => {
+ jest.clearAllMocks();
+ });
+
+ it('should register use case cards when workspace is enabled', () => {
+ const coreMock = {
+ createStart: jest.fn(() => ({
+ application: {
+ capabilities: {
+ workspaces: {
+ enabled: false,
+ },
+ },
+ navigateToApp: jest.fn(),
+ },
+ })),
+ };
+ const core = coreMock.createStart();
+
+ initHome(contentManagementStartMock, core);
+
+ expect(registerUseCaseCard).toHaveBeenCalledTimes(3);
+
+ expect(registerUseCaseCard).toHaveBeenCalledWith(contentManagementStartMock, core, {
+ id: DEFAULT_NAV_GROUPS.observability.id,
+ order: 1,
+ description: DEFAULT_NAV_GROUPS.observability.description,
+ title: DEFAULT_NAV_GROUPS.observability.title,
+ target: HOME_CONTENT_AREAS.GET_STARTED,
+ icon: DEFAULT_NAV_GROUPS.observability.icon ?? '',
+ navigateAppId: OBSERVABILITY_OVERVIEW_PAGE_ID,
+ });
+
+ expect(registerUseCaseCard).toHaveBeenCalledWith(contentManagementStartMock, core, {
+ id: DEFAULT_NAV_GROUPS.search.id,
+ order: 2,
+ description: DEFAULT_NAV_GROUPS.search.description,
+ title: DEFAULT_NAV_GROUPS.search.title,
+ target: HOME_CONTENT_AREAS.GET_STARTED,
+ icon: DEFAULT_NAV_GROUPS.search.icon ?? '',
+ navigateAppId: SEARCH_OVERVIEW_PAGE_ID,
+ });
+
+ expect(registerUseCaseCard).toHaveBeenCalledWith(contentManagementStartMock, core, {
+ id: DEFAULT_NAV_GROUPS['security-analytics'].id,
+ order: 3,
+ description: DEFAULT_NAV_GROUPS['security-analytics'].description,
+ title: DEFAULT_NAV_GROUPS['security-analytics'].title,
+ target: HOME_CONTENT_AREAS.GET_STARTED,
+ icon: DEFAULT_NAV_GROUPS['security-analytics'].icon ?? '',
+ navigateAppId: SECURITY_ANALYTICS_OVERVIEW_PAGE_ID,
+ });
+ });
+
+ it('should not register use case cards when workspace is disabled', () => {
+ const coreMock = {
+ createStart: jest.fn(() => ({
+ application: {
+ capabilities: {
+ workspaces: {
+ enabled: true,
+ },
+ },
+ },
+ })),
+ };
+ const core = coreMock.createStart();
+ initHome(contentManagementStartMock, core);
+ expect(registerUseCaseCard).not.toHaveBeenCalled();
+ });
+
+ it('should register home list cards correctly', () => {
+ const coreMock = {
+ createStart: jest.fn(() => ({
+ application: {
+ capabilities: {
+ workspaces: {
+ enabled: false,
+ },
+ },
+ },
+ })),
+ };
+ const core = coreMock.createStart();
+ initHome(contentManagementStartMock, core);
+
+ expect(registerHomeListCard).toHaveBeenCalledTimes(2);
+
+ expect(registerHomeListCard).toHaveBeenCalledWith(contentManagementStartMock, {
+ id: 'whats_new',
+ order: 10,
+ config: WHATS_NEW_CONFIG,
+ target: HOME_CONTENT_AREAS.SERVICE_CARDS,
+ width: 16,
+ });
+
+ expect(registerHomeListCard).toHaveBeenCalledWith(contentManagementStartMock, {
+ id: 'learn_opensearch_new',
+ order: 11,
+ config: LEARN_OPENSEARCH_CONFIG,
+ target: HOME_CONTENT_AREAS.SERVICE_CARDS,
+ width: 16,
+ });
+ });
+});
diff --git a/src/plugins/home/public/application/home_render.tsx b/src/plugins/home/public/application/home_render.tsx
index ef73d7c44d99..f22f3560205c 100644
--- a/src/plugins/home/public/application/home_render.tsx
+++ b/src/plugins/home/public/application/home_render.tsx
@@ -5,12 +5,16 @@
import React from 'react';
import { CoreStart } from 'opensearch-dashboards/public';
+import { DEFAULT_NAV_GROUPS } from '../../../../core/public';
import {
ContentManagementPluginSetup,
ContentManagementPluginStart,
HOME_PAGE_ID,
SECTIONS,
HOME_CONTENT_AREAS,
+ SEARCH_OVERVIEW_PAGE_ID,
+ OBSERVABILITY_OVERVIEW_PAGE_ID,
+ SECURITY_ANALYTICS_OVERVIEW_PAGE_ID,
} from '../../../../plugins/content_management/public';
import {
WHATS_NEW_CONFIG,
@@ -18,16 +22,13 @@ import {
registerHomeListCard,
} from './components/home_list_card';
+import { registerUseCaseCard } from './components/use_case_card';
+
export const setupHome = (contentManagement: ContentManagementPluginSetup) => {
contentManagement.registerPage({
id: HOME_PAGE_ID,
title: 'Home',
sections: [
- {
- id: SECTIONS.SERVICE_CARDS,
- order: 3000,
- kind: 'dashboard',
- },
{
id: SECTIONS.RECENTLY_VIEWED,
order: 2000,
@@ -47,10 +48,15 @@ export const setupHome = (contentManagement: ContentManagementPluginSetup) => {
);
},
},
+ {
+ id: SECTIONS.SERVICE_CARDS,
+ order: 3000,
+ kind: 'dashboard',
+ },
{
id: SECTIONS.GET_STARTED,
order: 1000,
- title: 'Get started with OpenSearch’s powerful features',
+ title: "Get started with OpenSearch's powerful features",
kind: 'card',
},
],
@@ -58,9 +64,34 @@ export const setupHome = (contentManagement: ContentManagementPluginSetup) => {
};
export const initHome = (contentManagement: ContentManagementPluginStart, core: CoreStart) => {
+ const workspaceEnabled = core.application.capabilities.workspaces.enabled;
+
+ if (!workspaceEnabled) {
+ const useCases = [
+ { ...DEFAULT_NAV_GROUPS.observability, navigateAppId: OBSERVABILITY_OVERVIEW_PAGE_ID },
+ { ...DEFAULT_NAV_GROUPS.search, navigateAppId: SEARCH_OVERVIEW_PAGE_ID },
+ {
+ ...DEFAULT_NAV_GROUPS['security-analytics'],
+ navigateAppId: SECURITY_ANALYTICS_OVERVIEW_PAGE_ID,
+ },
+ ];
+
+ useCases.forEach((useCase, index) => {
+ registerUseCaseCard(contentManagement, core, {
+ id: useCase.id,
+ order: index + 1,
+ description: useCase.description,
+ title: useCase.title,
+ target: HOME_CONTENT_AREAS.GET_STARTED,
+ icon: useCase.icon ?? '',
+ navigateAppId: useCase.navigateAppId,
+ });
+ });
+ }
+
registerHomeListCard(contentManagement, {
id: 'whats_new',
- order: 3,
+ order: 10,
config: WHATS_NEW_CONFIG,
target: HOME_CONTENT_AREAS.SERVICE_CARDS,
width: 16,
@@ -68,7 +99,7 @@ export const initHome = (contentManagement: ContentManagementPluginStart, core:
registerHomeListCard(contentManagement, {
id: 'learn_opensearch_new',
- order: 4,
+ order: 11,
config: LEARN_OPENSEARCH_CONFIG,
target: HOME_CONTENT_AREAS.SERVICE_CARDS,
width: 16,
diff --git a/src/plugins/saved_objects_management/public/management_section/recent_work.tsx b/src/plugins/saved_objects_management/public/management_section/recent_work.tsx
index eb04652d6343..88cdfc142af4 100644
--- a/src/plugins/saved_objects_management/public/management_section/recent_work.tsx
+++ b/src/plugins/saved_objects_management/public/management_section/recent_work.tsx
@@ -257,38 +257,45 @@ export const RecentWork = (props: { core: CoreStart; workspaceEnabled?: boolean
textAlign="left"
href={recentNavLink.href}
footer={
- <>
-
-
-
- {selectedSort === recentlyViewed
- ? i18n.translate(
- 'savedObjectsManagement.recentWorkSection.viewedAt',
- {
- defaultMessage: 'Viewed',
- }
- )
- : i18n.translate(
- 'savedObjectsManagement.recentWorkSection.updatedAt',
- {
- defaultMessage: 'Updated',
- }
- )}
- :{' '}
-
-
-
-
-
+
+
+
+
+
{selectedSort === recentlyViewed
- ? moment(recentAccessItem?.lastAccessedTime).fromNow()
- : moment(recentAccessItem?.updatedAt).fromNow()}
-
-
-
-
- {workspaceEnabled && (
- <>
+ ? i18n.translate(
+ 'savedObjectsManagement.recentWorkSection.viewedAt',
+ {
+ defaultMessage: 'Viewed',
+ }
+ )
+ : i18n.translate(
+ 'savedObjectsManagement.recentWorkSection.updatedAt',
+ {
+ defaultMessage: 'Updated',
+ }
+ )}
+ :{' '}
+
+
+
+
+
+ {selectedSort === recentlyViewed
+ ? moment(recentAccessItem?.lastAccessedTime).fromNow()
+ : moment(recentAccessItem?.updatedAt).fromNow()}
+
+
+
+
+
+ {workspaceEnabled && (
+
+
{i18n.translate(
@@ -300,15 +307,15 @@ export const RecentWork = (props: { core: CoreStart; workspaceEnabled?: boolean
:
-
+
{recentAccessItem.workspaceName || 'N/A'}
- >
- )}
-
- >
+
+
+ )}
+
}
onClick={recentNavLink.onClick}
/>
diff --git a/src/plugins/workspace/common/constants.ts b/src/plugins/workspace/common/constants.ts
index f66f7ea71752..22c746c0dbed 100644
--- a/src/plugins/workspace/common/constants.ts
+++ b/src/plugins/workspace/common/constants.ts
@@ -45,6 +45,7 @@ export const PRIORITY_FOR_PERMISSION_CONTROL_WRAPPER = 0;
* store a static map in workspace.
*
*/
+
export const WORKSPACE_USE_CASES = Object.freeze({
observability: {
id: 'observability',
@@ -52,9 +53,9 @@ export const WORKSPACE_USE_CASES = Object.freeze({
defaultMessage: 'Observability',
}),
description: i18n.translate('workspace.usecase.observability.description', {
- defaultMessage:
- 'Gain visibility into system health, performance, and reliability through monitoring and analysis of logs, metrics, and traces.',
+ defaultMessage: 'Gain visibility into your application and infrastructure',
}),
+ icon: 'wsObservability',
features: [
'discover',
'dashboards',
@@ -78,9 +79,9 @@ export const WORKSPACE_USE_CASES = Object.freeze({
defaultMessage: 'Security Analytics',
}),
description: i18n.translate('workspace.usecase.analytics.description', {
- defaultMessage:
- 'Detect and investigate potential security threats and vulnerabilities across your systems and data.',
+ defaultMessage: 'Enhance your security posture with advanced analytics',
}),
+ icon: 'wsSecurityAnalytics',
features: [
'discover',
'dashboards',
@@ -102,9 +103,9 @@ export const WORKSPACE_USE_CASES = Object.freeze({
defaultMessage: 'Essentials',
}),
description: i18n.translate('workspace.usecase.essentials.description', {
- defaultMessage:
- 'Analyze data to derive insights, identify patterns and trends, and make data-driven decisions.',
+ defaultMessage: 'Get start with just the basics',
}),
+ icon: 'wsEssentials',
features: [
'discover',
'dashboards',
@@ -125,9 +126,9 @@ export const WORKSPACE_USE_CASES = Object.freeze({
defaultMessage: 'Search',
}),
description: i18n.translate('workspace.usecase.search.description', {
- defaultMessage:
- "Quickly find and explore relevant information across your organization's data sources.",
+ defaultMessage: 'Discover and query your data with ease',
}),
+ icon: 'wsSearch',
features: [
'discover',
'dashboards',
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 cdcebca33e19..e1f47c9756d1 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
@@ -137,7 +137,7 @@ describe('Setup use case overview', () => {
"cardProps": Object {
"layout": "horizontal",
},
- "description": "Gain visibility into system health, performance, and reliability through monitoring and analysis of logs, metrics, and traces.",
+ "description": "Gain visibility into your application and infrastructure",
"getIcon": [Function],
"id": "observability",
"kind": "card",